根据 R 中的多个条件分配新的列值
Assign new column values based on multiple conditions in R
我需要分配一个新列,其中包含基于多个条件的多个可能值。
示例数据
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,则 return 1,否则,return 7。或者如果 a1 到 19 包含 5 或 6,return a 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
我知道这很笨拙,但在一定程度上是可行的。然而,一旦有多个值/条件,并非所有值都被正确填充(returns 可能是 3+ 个期望/分配值中的 2 个)。对于 'otherwise' 规则,我使用了 !=
以及 >
或 <
。
我也尝试过使用 ifelse
但效果相同。
我也知道解决方案会相对简单,而且会直接盯着我看,但如果你能给我指明一个合理的解决方案,我将不胜感激。
如果你有什么想让我澄清的,请告诉我。
提前致谢。
dplyr
中有一个向量化的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
)
)
条件在~
左边,你想要的结果在右边
Returns:
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,5 和 6 的行会发生什么?
7 还是 3?
无论如何,这里有一个可以根据以下内容进行调整的想法:
1 或 2 -> 1 ; 5 or 6 -> 6 (假设1 or 2和5 or 6不能混用) ;
否则 -> 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
函数代替循环
给你...一切都应该在那个 (base r) 循环中得到很好的解释。您只需要花一些时间创建一个系数文件,以便将其推广到其他数据。当您的条件发生变化时,您还必须进行一些调整(& 而不是 |,< 而不是 = 等)
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
我需要分配一个新列,其中包含基于多个条件的多个可能值。 示例数据
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,则 return 1,否则,return 7。或者如果 a1 到 19 包含 5 或 6,return a 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
我知道这很笨拙,但在一定程度上是可行的。然而,一旦有多个值/条件,并非所有值都被正确填充(returns 可能是 3+ 个期望/分配值中的 2 个)。对于 'otherwise' 规则,我使用了 !=
以及 >
或 <
。
我也尝试过使用 ifelse
但效果相同。
我也知道解决方案会相对简单,而且会直接盯着我看,但如果你能给我指明一个合理的解决方案,我将不胜感激。
如果你有什么想让我澄清的,请告诉我。
提前致谢。
dplyr
中有一个向量化的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
)
)
条件在~
左边,你想要的结果在右边
Returns:
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,5 和 6 的行会发生什么? 7 还是 3?
无论如何,这里有一个可以根据以下内容进行调整的想法: 1 或 2 -> 1 ; 5 or 6 -> 6 (假设1 or 2和5 or 6不能混用) ; 否则 -> 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
函数代替循环
给你...一切都应该在那个 (base r) 循环中得到很好的解释。您只需要花一些时间创建一个系数文件,以便将其推广到其他数据。当您的条件发生变化时,您还必须进行一些调整(& 而不是 |,< 而不是 = 等)
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