选择一列乘以,取决于其他变量的值

时间:2016-04-05 13:34:57

标签: r if-statement for-loop data.table apply

我仍在与R一起迈出第一步,发现SO是一个很好的工具,可以学习更多知识并找到问题的答案。对于这个我虽然没有找到任何好的解决方案。

我有一个可以简化为这种结构的数据框:

set.seed(10)
df <- data.frame(v1 = rep(1:2, times=3), 
v2 = c("A","B","B","A","B","A"), 
v3 = sample(1:6), 
xA_1 = sample(1:6), 
xA_2 = sample(1:6),
xB_1 = sample(1:6), xB_2 = sample(1:6))

df因此看起来像这样:

> df 
   v1 v2 v3   xA_1 xA_2 xB_1 xB_2
1  1  A  4    2    1    3    3
2  2  B  2    6    3    5    4
3  1  B  5    3    2    4    5
4  2  A  3    5    4    2    1
5  1  B  1    4    6    6    2
6  2  A  6    1    5    1    6

我现在希望R创建第四个变量,它取决于v1和v2的值。我通过使用以下代码实现了这一点:

df <- data.table(df)
df[, v4 := ifelse(v1 == 1 & v2 == "A", v3*xA_1, 
        ifelse(v1 == 1 & v2 == "B", v3*xB_1,
         ifelse(v1 == 2 & v2 == "A", v3*xA_2,
          ifelse(v1 == 2 & v2 == "B", v3*xB_2, v3*1))))]

因此,通过将v3与包含v1和v2值的列相乘来创建v4 (例如,对于第1行:v1=1 and v2=A thus multiply v3=4 with xA_1=2 -> 8)。

> df$v4
[1]  8  8 20 12  6 30

很明显,当v1和v2实际上具有比本例中更多不同的值时,我的ifelse方法很乏味。所以我正在寻找一种有效的方式告诉R if v1 == y & v2 == z, multiply v3 with column xy_z

我尝试编写for循环,编写一个y和z作为索引并使用apply函数的函数。然而,这一切都没有按照要求发挥作用。

我很感激任何想法!

3 个答案:

答案 0 :(得分:2)

这是一个基本R选项:

i <- paste0("x", df$v2, "_", df$v1)
df$v4 <- df$v3 * as.numeric(df[cbind(1:nrow(df), match(i, names(df)))])

对于下面提供的示例数据,它会创建一个列v4

> df$v4
[1] 25 12  2  6  3 10

或者,如果您希望包含“else”条件,则在没有匹配列名的情况下乘以1:

i <- paste0("x", df$v2, "_", df$v1)
tmp <- as.numeric(df[cbind(1:nrow(df), match(i, names(df)))])
df$v4 <- df$v3 * ifelse(is.na(tmp), 1, tmp)

示例数据:

df <- structure(list(v1 = c(1L, 2L, 1L, 2L, 1L, 2L), v2 = structure(c(1L, 
2L, 2L, 1L, 2L, 1L), .Label = c("A", "B"), class = "factor"), 
    v3 = c(5L, 4L, 1L, 6L, 3L, 2L), xA_1 = c(5L, 6L, 3L, 1L, 
    2L, 4L), xA_2 = c(6L, 4L, 2L, 1L, 3L, 5L), xB_1 = c(4L, 6L, 
    2L, 5L, 1L, 3L), xB_2 = c(5L, 3L, 2L, 4L, 1L, 6L)), .Names = c("v1", 
"v2", "v3", "xA_1", "xA_2", "xB_1", "xB_2"), row.names = c(NA, 
-6L), class = "data.frame")

答案 1 :(得分:2)

这是一个标准的“广泛”表格问题 - 您想要的更难做,但数据“融化”时很容易:

dt = as.data.table(df)

melt(dt, id.vars = c('v1', 'v2', 'v3'))[variable == paste0('x', v2, '_', v1)
   ][dt, on = c('v1', 'v2', 'v3'), v3 * value]
#[1]  8  8 20 12  6 30

答案 2 :(得分:0)

你可以试试这个:

v4 <- c()
for(i in 1:nrow(df)){
  col <- paste("x",df$v2[i],"_",df$v1[i],sep="")
  v4 <- c(v4,df$v3[i]*df[i,col])
}

df$v4 <- v4