library(dplyr)
##
## 次のパッケージを付け加えます: 'dplyr'
## 以下のオブジェクトは 'package:stats' からマスクされています:
##
## filter, lag
## 以下のオブジェクトは 'package:base' からマスクされています:
##
## intersect, setdiff, setequal, union
library(tibble)
set.seed(123)
<- 7
ncol <- 4
nrow <- matrix(rpois(ncol * nrow, 3), ncol = ncol, nrow = nrow)
d colnames(d) <- letters[1:ncol]
rownames(d) <- letters[23:(22 + nrow)]
print(d)
## a b c d e f g
## w 2 6 3 4 2 5 4
## x 4 0 3 3 0 4 4
## y 2 3 6 1 2 3 3
## z 5 5 3 5 6 8 3
Rでは、配列(array)や行列(matrix)だと、base
のmarginSums
関数で周辺合計が計算できますが、この関数はデータフレームには適用できません。janitor
パッケージを使うと簡単にできるそうなのですが、dplyr
でなんとかしてみました。
準備
まずは、dplyr
パッケージとtibble
パッケージを読み込み、さらにデータを作成します。
marginSums
関数
行列ならmarginSums
関数で周辺合計が計算できます。
marginSums(d, 1)
## w x y z
## 26 18 20 35
marginSums(d, 2)
## a b c d e f g
## 13 14 15 13 10 20 14
データをtibble
形式に変換して、行の名前をname
という列に入れるようにしました。
<- as_tibble(d) %>%
tbl add_column(name = letters[23:(22 + nrow)]) %>%
relocate(name, letters[1:ncol])
print(tbl)
## # A tibble: 4 × 8
## name a b c d e f g
## <chr> <int> <int> <int> <int> <int> <int> <int>
## 1 w 2 6 3 4 2 5 4
## 2 x 4 0 3 3 0 4 4
## 3 y 2 3 6 1 2 3 3
## 4 z 5 5 3 5 6 8 3
tibble
に対してmarginSums
関数を適用しようとすると、
marginSums(tbl, 1)
「marginSums(tbl, 1) でエラー: ‘x’ は配列ではありません」といわれてしまいます。
dplyr
で計算する場合
そこで、dplyr
のrowwise
関数を使い、sum(c_across(-name))
として、name
以外の各行の合計を求め、totalという列に入れるようにしました。
<- tbl %>%
tbl_rtot rowwise() %>%
mutate(total = sum(c_across(-name)))
print(tbl_rtot)
## # A tibble: 4 × 9
## # Rowwise:
## name a b c d e f g total
## <chr> <int> <int> <int> <int> <int> <int> <int> <int>
## 1 w 2 6 3 4 2 5 4 26
## 2 x 4 0 3 3 0 4 4 18
## 3 y 2 3 6 1 2 3 3 20
## 4 z 5 5 3 5 6 8 3 35
次に、name
以外の各列の合計を求めます。ungroup
でrowwise
を解除しておきます。
<- tbl_rtot %>%
col_sum ungroup() %>%
summarise(across(-name, sum))
print(col_sum)
## # A tibble: 1 × 8
## a b c d e f g total
## <int> <int> <int> <int> <int> <int> <int> <int>
## 1 13 14 15 13 10 20 14 99
tibble
のadd_row
関数で元の表の最後の行として、周辺合計を追加します。これで、周辺合計(と総計)を追加した表の完成です。
<- tbl_rtot %>%
tbl_total add_row(bind_cols(name = "total", col_sum))
print(tbl_total)
## # A tibble: 5 × 9
## # Rowwise:
## name a b c d e f g total
## <chr> <int> <int> <int> <int> <int> <int> <int> <int>
## 1 w 2 6 3 4 2 5 4 26
## 2 x 4 0 3 3 0 4 4 18
## 3 y 2 3 6 1 2 3 3 20
## 4 z 5 5 3 5 6 8 3 35
## 5 total 13 14 15 13 10 20 14 99