如何在不在数据帧中写入循环的情况下多次获取两列的差异

时间:2017-08-16 10:53:26

标签: r

我的数据看起来像这样

[[1897, 135, 130, 127, 70, 162, 445, 656, 608, 1019], [1897, 364, 56, 1236, 181, 172, 449, 48, 15, 18], [1897, 163, 11, 70, 166, 345, 480, 9, 60, 351]]

我想添加ID A_w B_w C_w A_b B_b C_b 1 3 4 6 0.5 0.2 0.9 2 6 5 7 1.4 3.2 7.6 3 12 11 27 5.4 3.2 6.1 等新列(A_c = A_w - A_bB_c相同)。最简单的方法可能是写一个循环,但我想知道是否可以使用C_capply来完成。如您所见,变量名称具有模式。此外,它始终是lapplydataframe[, x]之间的差异。

作为R的新手,我发现R文档不是很有帮助。例如,如果我没有意外地看到dataframe[, x+3]用于表示.SD中的子集,我将永远不知道它的存在,因为它没有在R文档或任何其他在线提及教程。实际上,堆栈溢出是我看到人们询问lapply的唯一地方。任何处理此类情况的建议都将受到赞赏!

2 个答案:

答案 0 :(得分:2)

基于R的想法,使用sapply对唯一名称(_之前)。然后使用Reduce减去与唯一名称匹配的列,即

m1 <- sapply(unique(sub('_.*', '', names(df[-1]))), function(i)
                                               Reduce(`-`, df[grepl(i, names(df))]))

#tidy and bind with original df, 
cbind(df, setNames(data.frame(m1), paste0(colnames(m1), '_c')))

或者避免cbind并按照@lmo建议直接进行,

baseNames <- unique(sub('_.*', '', names(df[-1])))
df[paste(baseNames, "c", sep="_")] <- sapply(baseNames, function(i)
                                                     Reduce(`-`, df[grepl(i, names(df))]))

矢量化解决方案

既然你提到另外,它始终是dataframe [,x]和dataframe [,x + 3] 之间的差异,那么完全向量化的方式就是(保持baseNames从之前),

m1 <- matrix(seq(ncol(df)-1)+1, ncol = 2)
df[paste(baseNames, "c", sep="_")] <- df[m1[,1]] - df[m1[,2]]

上述所有内容,

  ID A_w B_w C_w A_b B_b C_b A_c B_c  C_c
1  1   3   4   6 0.5 0.2 0.9 2.5 3.8  5.1
2  2   6   5   7 1.4 3.2 7.6 4.6 1.8 -0.6
3  3  12  11  27 5.4 3.2 6.1 6.6 7.8 20.9 

答案 1 :(得分:0)

使用tidyrdplyr即可:

library(tidyr)
library(dplyr)
df1 <- read.table(text="ID   A_w B_w C_w  A_b  B_b  C_b
1    3   4   6   0.5  0.2  0.9
2    6   5   7   1.4  3.2  7.6
3   12   11  27  5.4  3.2  6.1",header=T,stringsAsFactors=F)

df1 %>% gather(var,val,-ID) %>%
  separate(var,c("var1","var2")) %>%
  spread(var2,val) %>%
  mutate(c=w-b) %>%
  gather(var2,val,-ID,-var1) %>%
  unite(var,c("var1","var2")) %>%
  spread(var,val)

  ID A_b A_c A_w B_b B_c B_w C_b  C_c C_w
1  1 0.5 2.5   3 0.2 3.8   4 0.9  5.1   6
2  2 1.4 4.6   6 3.2 1.8   5 7.6 -0.6   7
3  3 5.4 6.6  12 3.2 7.8  11 6.1 20.9  27