web-dev-qa-db-ja.com

合計を含むデータフレームに行を追加するにはどうすればよいですか?

列の値を合計する行を追加するデータフレームがあります。たとえば、次のデータがあるとします。

_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列にも同じことが起こります。

これを行うためのより良い方法は何ですか?

32
Lorin Hochstein

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()を含むこのパッケージを作成しました。

25
Sam Firke

ここにあなたが望むものを手に入れる方法がありますが、もっとエレガントなソリューションがあるかもしれません。

rbind(x, data.frame(Language="Total",t(colSums(x[,-1]))))

記録に関しては、Language列が絶対に必要でない場合は、Chaseの答えを好みます。

23
Joshua Ulrich

データに言語列が必要ですか、それともその列を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
20
Chase

これを行う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")))
15
Matifou

これを試して

y[4,] = c("Total", colSums(y[,2:3]))
9
Prateek Joshi

(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
6
G. Grothendieck

データフレームに列の合計を本当に含めたいですか?私にとって、データフレームの解釈は行に依存するようになりました。例えば、

  • 行1n-1):---(特定言語に関連付けられているファイルの数
  • 行n:all言語に関連付けられているファイルの数

データのサブセット化を開始すると、これはさらに混乱します。たとえば、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行が間違っています!

個人的には、列の合計を計算し、別のベクトルに保存します。

1
csgillespie

これはプレゼンテーション用にエクスポートする前の最後のステップであるため、明確にするために列名にスペースを含めることができます(つまり、「総計」)。その場合、以下は、作成されたdata.frameが、列名の不一致によるエラーなしで元のデータセットにバインドすることを保証します。

dfTotals <- data.frame(Language="Total",t(colSums(x[,-1]))))

colnames(dfTotals) <- names(x)  

rbind(x, dfTotals)
1
BobD59

列を数値に強制すると、元の本能が機能します。

y$LOC <- as.numeric(y$LOC)
y$Files <- as.numeric(y$Files)

そして、colSums()とrbind()を適用します。

0