列の値を合計する行を追加するデータフレームがあります。たとえば、次のデータがあるとします。
_x <- data.frame(Language=c("C++", "Java", "Python"),
Files=c(4009, 210, 35),
LOC=c(15328,876, 200),
stringsAsFactors=FALSE)
_
データは次のようになります。
_ Language Files LOC
1 C++ 4009 15328
2 Java 210 876
3 Python 35 200
_
私の本能はこれをすることです:
_y <- rbind(x, c("Total", colSums(x[,2:3])))
_
そしてこれは機能し、合計を計算します:
_> y
Language Files LOC
1 C++ 4009 15328
2 Java 210 876
3 Python 35 200
4 Total 4254 16404
_
問題は、Files列とLOC列がすべて文字列に変換されていることです。
_> y$LOC
[1] "15328" "876" "200" "16404"
_
これは、数字と文字列の両方の入力を持つベクターc("Total", colSums(x[,2:3])
を作成し、すべての要素を共通の型に変換してすべてのベクター要素が同じになるために発生していることを理解しています。次に、Files列とLOC列にも同じことが起こります。
これを行うためのより良い方法は何ですか?
Janitorパッケージのadorn_totals()
を参照してください。
_library(janitor)
x %>%
adorn_totals("row")
#> Language Files LOC
#> C++ 4009 15328
#> Java 210 876
#> Python 35 200
#> Total 4254 16404
_
数値列はクラスnumericのままです。
免責事項:このタスク用に作成されたadorn_totals()
を含むこのパッケージを作成しました。
ここにあなたが望むものを手に入れる方法がありますが、もっとエレガントなソリューションがあるかもしれません。
rbind(x, data.frame(Language="Total",t(colSums(x[,-1]))))
記録に関しては、Language
列が絶対に必要でない場合は、Chaseの答えを好みます。
データに言語列が必要ですか、それともその列をrow.names
?これにより、data.frameが3つの変数の4つの観測値から2つの変数の4つの観測値(Files&LOC)に変更されます。
x <- data.frame(Files=c(4009, 210, 35), LOC=c(15328,876, 200), row.names=c("C++", "Java", "Python"), stringsAsFactors=F)
x["Total" ,] <- colSums(x)
> x
Files LOC
C++ 4009 15328
Java 210 876
Python 35 200
Total 4254 16404
これを行うtidyverse
方法は、bind_rows
(または最終的にadd_rows
)およびsummarise
で合計を計算します。ここでの問題は、1つを除くすべての合計が必要なことです。そのため、コツは次のとおりです。
summarise_all(x, funs(if(is.numeric(.)) sum(.) else "Total"))
1行で:
x %>%
bind_rows(summarise_all(., funs(if(is.numeric(.)) sum(.) else "Total")))
これを試して
y[4,] = c("Total", colSums(y[,2:3]))
(1)最初の列に"Language"
見出しが必要ない場合、行名を使用してそれを表すことができ、(2)最後の行に"Sum"
ではなく"Total"
のラベルを付けてもよい場合は、addmargins
このような:
rownames(x) <- x$Language
addmargins(as.table(as.matrix(x[-1])), 1)
与える:
Files LOC
C++ 4009 15328
Java 210 876
Python 35 200
Sum 4254 16404
最初の列に"Language"
というラベルを付け、合計行に"Total"
というラベルを付けたい場合は、少し長くします。
rownames(x) <- x$Language
Total <- sum
xa <- addmargins(as.table(as.matrix(x[-1])), 1, FUN = Total)
data.frame(Language = rownames(xa), as.matrix(xa[]), row.names = NULL)
与える:
Language Files LOC
1 C++ 4009 15328
2 Java 210 876
3 Python 35 200
4 Total 4254 16404
データフレームに列の合計を本当に含めたいですか?私にとって、データフレームの解釈は行に依存するようになりました。例えば、
データのサブセット化を開始すると、これはさらに混乱します。たとえば、100個を超えるファイルを持つ言語を知りたいとします。
> x = data.frame(Files=c(4009, 210, 35),
LOC=c(15328,876, 200),
row.names=c("C++", "Java", "Python"),
stringsAsFactors=FALSE)
> x["Total" ,] = colSums(x)
> x[x$Files > 100,]
Files LOC
C++ 4009 15328
Java 210 876
Total 4254 16404#But this refers to all languages!
Total
行が間違っています!
個人的には、列の合計を計算し、別のベクトルに保存します。
これはプレゼンテーション用にエクスポートする前の最後のステップであるため、明確にするために列名にスペースを含めることができます(つまり、「総計」)。その場合、以下は、作成されたdata.frameが、列名の不一致によるエラーなしで元のデータセットにバインドすることを保証します。
dfTotals <- data.frame(Language="Total",t(colSums(x[,-1]))))
colnames(dfTotals) <- names(x)
rbind(x, dfTotals)
列を数値に強制すると、元の本能が機能します。
y$LOC <- as.numeric(y$LOC)
y$Files <- as.numeric(y$Files)
そして、colSums()とrbind()を適用します。