我需要根据多个条件分配一个新列,其中包含多个可能的值。 示例数据
a1 a2 a3 a4 a5 a6 a7 a8 a9
NA 1 NA 2 7 8 9 1 1
7 7 7 7 7 7 7 7 7
6 6 6 6 6 6 5 5 5
所以我可能有规则例如:如果a1到a9包含1或2然后返回1,否则返回7.或如果a1到19包含5或6,则返回6,否则3.我有一个这些规则需要一些可以容纳的东西。
要求的结果
a1 a2 a3 a4 a5 a6 a7 a8 a9 NEW
NA 1 NA 2 7 8 9 1 1 1
7 7 7 7 7 7 7 7 7 7
6 6 6 6 6 6 5 5 5 6
我尝试过分配,即。
df$NEW <- 7
df$NEW[df$a1==1 | df$a2==1 | df$a3==1] <- 1
df$NEW[df$a4==1 | df$a5==1 | df$a6==1] <- 1
df$NEW[df$a7==1 | df$a8==1 | df$a9==1] <- 1
df$NEW[df$a1==7 | df$a2==7 | df$a3==7] <- 7
df$NEW[df$a1==5 | df$a2==5 | df$a3==5] <- 6
df$NEW[df$a1==6 | df$a2==6 | df$a3==6] <- 6
我所知道的是笨重的,但在某种程度上是有效的。然而,一旦有多个值/条件,并非所有值都被正确填充(返回3个期望/指定值中的2个)。对于我使用!=
以及>
或<
的“其他”规则。
我也尝试使用ifelse
,但效果相同。
我也知道解决方案会相对简单并且盯着我看,但我很感激你让我找到一个合理的解决方案。
如果你有什么需要我澄清的,请告诉我。
提前致谢。
答案 0 :(得分:2)
dplyr
中有一个vectorised if语句可以帮助您调用case_when
:
library(dplyr)
df <- read.table(text = 'a1 a2 a3 a4 a5 a6 a7 a8 a9
NA 1 NA 2 7 8 9 1 1
7 7 7 7 7 7 7 7 7
6 6 6 6 6 6 5 5 5', header = T)
df %>%
mutate(
NEW = case_when(
a1 == 1 | a2 == 1 | a3 == 1 ~ 1,
a1==1 | a2==1 | a3==1 ~ 1,
a4==1 | a5==1 | a6==1 ~ 1,
a7==1 | a8==1 | a9==1 ~ 1,
a1==7 | a2==7 | a3==7 ~ 7,
a1==5 | a2==5 | a3==5 ~ 6,
a1==6 | a2==6 | a3==6 ~ 6
)
)
条件位于~
的左侧,您想要的结果位于右侧。
返回:
a1 a2 a3 a4 a5 a6 a7 a8 a9 NEW
1 NA 1 NA 2 7 8 9 1 1 1
2 7 7 7 7 7 7 7 7 7 7
3 6 6 6 6 6 6 5 5 5 6
答案 1 :(得分:2)
这是一个适用于多个规则的想法。 但是你的例子不清楚,没有1,2,5和6的线路会发生什么? 7或3?
无论如何,这里的想法适应性基于: 1或2 - &gt; 1; 5或6 - &gt; 6(假设1或2和5或6不能混合); 否则 - &gt; 7
df$new <- 7
for (i in 1:nrow(df)) {
if (1 %in% as.numeric(df[i,]) | 2 %in% as.numeric(df[i,] )) {
df[i,]$new <- 1
}
else if (5 %in% as.numeric(df[i,]) | 6 %in% as.numeric(df[i,] )) {
df[i,]$new <- 6
}
}
df
您可以使用apply
函数代替循环
答案 2 :(得分:1)
在这里,你应该在那个(基础r)循环中很好地解释一切。您只需花一些时间创建系数文件,以便将其推广到其他数据。当你的条件发生变化时,你也需要调整一下(&amp;而不是|,&lt;而不是= etc。)
df <-data.frame(matrix(c(NA, 1, NA, 2, 7, 8, 9, 1, 1,7, 7, 7, 7, 7, 7, 7, 7, 7,6, 6, 6, 6, 6, 6, 5, 5, 5),
nrow=3, ncol=9, byrow=T))
colnames(df) = c("a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9" )
nbconditions <- 6
condition <- matrix(NA, nrow=nrow(df) , ncol= nbconditions)
# you could read.xlsx an already prepared coefficient matrix here
coefficients <- matrix(NA, nrow= ncol(df) , ncol=nbconditions )
coefficients[c(1,2,3),1] <- 1
coefficients[c(4,5,6),2] <- 1
coefficients[c(7,8,9),3] <- 1
coefficients[c(1,2,3),4] <- 7
coefficients[c(1,2,3),5] <- 5
coefficients[c(1,2,3),6] <- 6
results <- c(1,1,1,7,6,6)
NEW <- rep(NA, nrow(df))
for(i in 1:nrow(df)) {
found <- F
for(j in nbconditions:1) { #condition checking from least priority to most priority
if(!found) {
indicestocheck <- which(!is.na(coefficients[,j]))
if(sum(is.na(df[i,indicestocheck]))==length(indicestocheck)) {
NEW[i] <- NA
} else {
checks <- (coefficients[,j] == df[i,indicestocheck])
#print(checks)
if( sum(is.na(checks)) < length(checks) & 1<=sum(checks[which(!is.na(checks))])) {
NEW[i] <- results[j]
found <- T
print(paste(j,"found",results[i]))
}
}
}
}
}
df$NEW <- NEW
df
> df
a1 a2 a3 a4 a5 a6 a7 a8 a9 NEW
1 NA 1 NA 2 7 8 9 1 1 1
2 7 7 7 7 7 7 7 7 7 7
3 6 6 6 6 6 6 5 5 5 6