在R中,将多列的行总和分配给其他列

时间:2020-08-08 00:06:38

标签: r

希望有人可以告诉我如何使用更优雅的方式来简化我的代码,以完成我在R中要做的事情。

现有data.frame:

names <- c("ADD1_T1", "ADD2_T1", "ADD3_T1", "ADD4_T1", "ADD5_T1", "ADD6_T1", "ADD7_T1", "ADD8_T1", "ADD9_T1", "SS_ADD1_T1", "SS_ADD2_T1", "SS_ADD3_T1", "SS_ADD4_T1", "SS_ADD5_T1", "SS_ADD6_T1", "SS_ADD7_T1", "SS_ADD8_T1", "SS_ADD9_T1", "TT_ADD1_T1", "TT_ADD2_T1", "TT_ADD3_T1", "TT_ADD4_T1", "TT_ADD5_T1", "TT_ADD6_T1", "TT_ADD7_T1", "TT_ADD8_T1", "TT_ADD9_T1", "XX_ADD1_T1", "XX_ADD2_T1", "XX_ADD3_T1", "XX_ADD4_T1", "XX_ADD5_T1", "XX_ADD6_T1", "XX_ADD7_T1", "XX_ADD8_T1", "XX_ADD9_T1", "GG_ADD1_T1", "GG_ADD2_T1", "GG_ADD3_T1", "GG_ADD4_T1", "GG_ADD5_T1", "GG_ADD6_T1", "GG_ADD7_T1", "GG_ADD8_T1", "GG_ADD9_T1", "ADD1_T2", "ADD2_T2", "ADD3_T2", "ADD4_T2", "ADD5_T2", "ADD6_T2", "ADD7_T2", "ADD8_T2", "ADD9_T2", "SS_ADD1_T2", "SS_ADD2_T2", "SS_ADD3_T2", "SS_ADD4_T2", "SS_ADD5_T2", "SS_ADD6_T2", "SS_ADD7_T2", "SS_ADD8_T2", "SS_ADD9_T2", "TT_ADD1_T2", "TT_ADD2_T2", "TT_ADD3_T2", "TT_ADD4_T2", "TT_ADD5_T2", "TT_ADD6_T2", "TT_ADD7_T2", "TT_ADD8_T2", "TT_ADD9_T2", "XX_ADD1_T2", "XX_ADD2_T2", "XX_ADD3_T2", "XX_ADD4_T2", "XX_ADD5_T2", "XX_ADD6_T2", "XX_ADD7_T2", "XX_ADD8_T2", "XX_ADD9_T2", "GG_ADD1_T2", "GG_ADD2_T2", "GG_ADD3_T2", "GG_ADD4_T2", "GG_ADD5_T2", "GG_ADD6_T2", "GG_ADD7_T2", "GG_ADD8_T2", "GG_ADD9_T2")
df <- data.frame()
for (k in names) df[[k]] <- as.character()
df[nrow(df)+20,] <- NA
df[10:ncol(df)] <- sample(0:1, size = 20, replace = TRUE)

希望使用尽可能少的代码行在R中执行以下操作。可能只用几行代码(而不是18行)就可以做到吗?

ADD1_T1  = as.numeric(rowSums(df[, c("SS_ADD1_T1" , "TT_ADD1_T1" , "XX_ADD1_T1" , "GG_ADD1_T1") ], na.rm=TRUE)>0)
ADD2_T1  = as.numeric(rowSums(df[, c("SS_ADD2_T1" , "TT_ADD2_T1" , "XX_ADD2_T1" , "GG_ADD2_T1") ], na.rm=TRUE)>0)
...
ADD9_T1  = as.numeric(rowSums(df[, c("SS_ADD9_T1" , "TT_ADD9_T1" , "XX_ADD9_T1" , "GG_ADD9_T1") ], na.rm=TRUE)>0)

...

ADD1_T2  = as.numeric(rowSums(df[, c("SS_ADD1_T2" , "TT_ADD1_T2" , "XX_ADD1_T2" , "GG_ADD1_T2") ], na.rm=TRUE)>0)
ADD2_T2  = as.numeric(rowSums(df[, c("SS_ADD2_T2" , "TT_ADD2_T2" , "XX_ADD2_T2" , "GG_ADD2_T2") ], na.rm=TRUE)>0)
...
ADD9_T2  = as.numeric(rowSums(df[, c("SS_ADD9_T2" , "TT_ADD9_T2" , "XX_ADD9_T2" , "GG_ADD9_T2") ], na.rm=TRUE)>0)

3 个答案:

答案 0 :(得分:2)

考虑将所有列实际定义为数字

for (k in names) df[[k]] <- as.numeric()

您可以在此处创建结果矩阵,方法是使用outer + paste0创建词干名称向量,然后使用sapply + grep进行迭代:

ADD_nms <- as.vector(outer(1:9, 1:2, function(x,y) paste0("ADD", x, "_T", y)))
ADD_nms
# [1] "ADD1_T1" "ADD2_T1" "ADD3_T1" "ADD4_T1" "ADD5_T1" "ADD6_T1" "ADD7_T1" 
# [8] "ADD8_T1" "ADD9_T1" "ADD1_T2" "ADD2_T2" "ADD3_T2" "ADD4_T2" "ADD5_T2" 
# [15] "ADD6_T2" "ADD7_T2" "ADD8_T2" "ADD9_T2"

ADD_matrix <- sapply(ADD_nms, function(x) 
    as.numeric(rowSums(df[, grep(x, names(df))], na.rm=TRUE)>0))

ADD_matrix

Online Demo

答案 1 :(得分:0)

您可以重塑数据集: 由于您的数据到处都有相同的值,因此最好进行一些随机化处理,即:

df[10:ncol(df)] <-  sample(0:1,20 * 81, replace = TRUE)

现在您可以做什么:

nms <- names(df)
index<- grep("_ADD", nms)
A <- matrix(names(df)[index], 9)
B <- rbind(A[,1:4],A[,5:8])
df1 <- reshape(df[c(B)], t(B), dir="long", times = sub(".._","",B[,1]))
s <- grep("^(id|time)$",names(df1))
D <- by(df1[-s], df1$time, function(x) as.integer(rowSums(x, na.rm = TRUE) > 0))
df[match(names(D), nms[-index])] <- D

现在您可以计算任何值并与df中的列进行比较

答案 2 :(得分:-1)

在基本R中,您可以使用 apply()功能。参见This

一个有趣的(推荐的替代方法)是使用 tydyverse 中的 group_by 功能。参见This