2016-05-19 14 views
0

スプレッドシートに100を超える列があり、多くの列に同じ名前があります。これらの列を同じ名前でマージし、それらの列の値を行合計したいとします。私は条件付き実行if()がそれを行う必要がありますが、私は同じ列名の条件を記述するのに苦労していると思いますか?列をマージして合計する機能は何でしょうか?マージ()?またはrowsum()?R:同じ列名を持つ列と値のマージ

aa <- read.table()

if (colnames(aa) ==) merge/rowsum()

ありがとうございます。

これは、それが今どのように見えるかのサンプルです:

B C U B C 
1 1 1 1 1 
2 2 2 2 2 
3 3 3 3 3 
4 4 4 4 4 

そして、これは私が得ることを期待するものである:カラム数の削減をし、合併時に値を合計します。それを行うには

B C U 
2 2 1 
4 4 2 
6 6 3 
8 8 4 

答えて

3

ソリューション1

split()lapply()rowSums()、およびdo.call()/cbind()

do.call(cbind,lapply(split(seq_len(ncol(df)),names(df)),function(x) rowSums(df[x]))); 
##  B C U 
## [1,] 2 2 1 
## [2,] 4 4 2 
## [3,] 6 6 3 
## [4,] 8 8 4 

溶液2

Reduce()/`+`()rowSums()呼の交換:

do.call(cbind,lapply(split(seq_len(ncol(df)),names(df)),function(x) Reduce(`+`,df[x]))); 
##  B C U 
## [1,] 2 2 1 
## [2,] 4 4 2 
## [3,] 6 6 3 
## [4,] 8 8 4 

溶液3

は(unclassedリストとして)data.frameを分割してインデックスベクトル仲介の交換直接:

do.call(cbind,lapply(split(as.list(df),names(df)),function(x) Reduce(`+`,x))); 
##  B C U 
## [1,] 2 2 1 
## [2,] 4 4 2 
## [3,] 6 6 3 
## [4,] 8 8 4 

ベンチマーク

library(microbenchmark); 

bgoldst1 <- function(df) do.call(cbind,lapply(split(seq_len(ncol(df)),names(df)),function(x) rowSums(df[x]))); 
bgoldst2 <- function(df) do.call(cbind,lapply(split(seq_len(ncol(df)),names(df)),function(x) Reduce(`+`,df[x]))); 
bgoldst3 <- function(df) do.call(cbind,lapply(split(as.list(df),names(df)),function(x) Reduce(`+`,x))); 
sotos <- function(df) sapply(unique(names(df)), function(i)rowSums(df[names(df) == i])); 

df <- data.frame(B=c(1L,2L,3L,4L),C=c(1L,2L,3L,4L),U=c(1L,2L,3L,4L),B=c(1L,2L,3L,4L),C=c(1L,2L,3L,4L),check.names=F); 

ex <- bgoldst1(df); 
all.equal(ex,sotos(df)[,colnames(ex)]); 
## [1] TRUE 
all.equal(ex,bgoldst2(df)); 
## [1] TRUE 
all.equal(ex,bgoldst3(df)); 
## [1] TRUE 

microbenchmark(bgoldst1(df),bgoldst2(df),bgoldst3(df),sotos(df)); 
## Unit: microseconds 
##   expr  min  lq  mean median  uq  max neval 
## bgoldst1(df) 245.473 258.3030 278.9499 272.4155 286.742 641.052 100 
## bgoldst2(df) 156.949 166.3580 184.2206 171.7030 181.539 1042.618 100 
## bgoldst3(df) 82.110 92.5875 100.9138 97.2915 107.128 170.207 100 
##  sotos(df) 200.997 211.9030 226.7977 223.6630 235.210 328.010 100 

set.seed(1L); 
NR <- 1e3L; NC <- 1e3L; 
df <- setNames(nm=LETTERS[sample(seq_along(LETTERS),NC,T)],data.frame(replicate(NC,sample(seq_len(NR*3L),NR,T)))); 

ex <- bgoldst1(df); 
all.equal(ex,sotos(df)[,colnames(ex)]); 
## [1] TRUE 
all.equal(ex,bgoldst2(df)); 
## [1] TRUE 
all.equal(ex,bgoldst3(df)); 
## [1] TRUE 

microbenchmark(bgoldst1(df),bgoldst2(df),bgoldst3(df),sotos(df)); 
## Unit: milliseconds 
##   expr  min  lq  mean median  uq  max neval 
## bgoldst1(df) 11.070218 11.586182 12.745706 12.870209 13.234997 16.15929 100 
## bgoldst2(df) 4.534402 4.680446 6.161428 6.097900 6.425697 44.83254 100 
## bgoldst3(df) 3.430203 3.555505 5.355128 4.919931 5.219930 41.79279 100 
##  sotos(df) 19.953848 21.419628 22.713282 21.829533 22.280279 60.86525 100 
+0

hah ...素晴らしい。ありがとうございました:) – Sotos

+0

全く問題ありません:) – bgoldst

+1

ありがとう、bgoldst!ソリューション1と2がこのエラーを出しました:df [x]のエラー: 'closure'タイプのオブジェクトはサブセット化できません。しかし、ソリューション3が働いた。私のために十分に良い! –

2

一つの方法、使用

sapply(unique(names(df)), function(i)rowSums(df[names(df) == i])) 

#  B C U 
#[1,] 2 2 1 
#[2,] 4 4 2 
#[3,] 6 6 3 
#[4,] 8 8 4 
1

ここdata.tableからmelt/dcastを持つ別のオプションがあります。 'data.frame'を 'data.table'(setDT(df1))に変換し、行番号列( 'rn')、meltを 'wide'から 'long'形式に作成し、dcastを 'wide'に指定します。 fun.aggregatesumとする。

library(data.table) 
setDT(df1)[, rn := 1:.N] 
dcast(melt(df1, id.var= "rn"), rn ~variable, value.var="value", sum)[, rn:= NULL][] 
# B C U 
#1: 2 2 1 
#2: 4 4 2 
#3: 6 6 3 
#4: 8 8 4 
関連する問題