4

我正在根据另一个的 TRUE/FALSE 状态计算一个新变量:

value<-c(2, 4, 5, 8, 2, 3, 1)
tf<-c(TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE)
df<-data.frame(value, tf)

以下代码可以满足我的需要(如果 'tf' 为 TRUE,则将 'value' 减半)...

df$newVals[which(df$tf)]<-df$value[which(df$tf)]/2
df$newVals[which(!df$tf)]<-df$value[which(!df$tf)]

...但感觉太复杂了。有没有更简单的方法?

谢谢

4

4 回答 4

8

这是一个非常简单的解决方案,没有ifelse

df$newVals <- with(df, value / (tf + 1))

这个怎么运作?

如果布尔值(如tf)与数学运算符一起使用,则会将它们转换为数值(FALSE转换为0TRUE转换为1)。因此,该命令tf + 1创建了一个1s 和2s 的数值向量。中的值value除以这个新向量中的值。除以一不会改变原始值。

于 2012-11-08T15:12:11.893 回答
6

你可以这样做ifelse

value<-c(2, 4, 5, 8, 2, 3, 1)
tf<-c(TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE)
df<-data.frame(value, tf)

df$newVals <- with(df, ifelse(tf, value/2, value))
于 2012-11-08T14:59:17.463 回答
4

使用ifelse并将transform为您完成

 transform(df, newVals=ifelse(tf, value/2,value))
      value    tf newVals
    1     2  TRUE     1.0
    2     4 FALSE     4.0
    3     5 FALSE     5.0
    4     8 FALSE     8.0
    5     2  TRUE     1.0
    6     3 FALSE     3.0
    7     1  TRUE     0.5
于 2012-11-08T14:59:57.993 回答
1

略有不同的策略;只需更新需要更改的值而不是所有值,然后使用ifelse(). 例如

value<-c(2, 4, 5, 8, 2, 3, 1)
tf<-c(TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE)
df<-data.frame(value, tf)

df <- transform(df, newVals = value) ## task a copy of `value`
df[df$tf, "newVals"] <- df[df$tf, "value"] / 2 ## update only ones we want
df

给予

> df
  value    tf newVals
1     2  TRUE     1.0
2     4 FALSE     4.0
3     5 FALSE     5.0
4     8 FALSE     8.0
5     2  TRUE     1.0
6     3 FALSE     3.0
7     1  TRUE     0.5

如果您不喜欢所有索引,则可以将其分解一下-只需创建ind包含以下行的索引的tf索引TRUE

df <- transform(df, newVals = value)
ind <- with(df, which(tf))
df[ind, "newVals"] <- df[ind, "value"] / 2
df

> df
  value    tf newVals
1     2  TRUE     1.0
2     4 FALSE     4.0
3     5 FALSE     5.0
4     8 FALSE     8.0
5     2  TRUE     1.0
6     3 FALSE     3.0
7     1  TRUE     0.5
于 2012-11-08T15:15:30.300 回答