2011-11-21 230 views
48

我想了解如何在不使用循环的情况下条件替换数据框中的值。我的数据帧结构如下:条件替换data.frame中的值

> df 
      a b est 
1 11.77000 2 0 
2 10.90000 3 0 
3 10.32000 2 0 
4 10.96000 0 0 
5 9.90600 0 0 
6 10.70000 0 0 
7 11.43000 1 0 
8 11.41000 2 0 
9 10.48512 4 0 
10 11.19000 0 0 

dput输出是这样的:

structure(list(a = c(11.77, 10.9, 10.32, 10.96, 9.906, 10.7, 
11.43, 11.41, 10.48512, 11.19), b = c(2, 3, 2, 0, 0, 0, 1, 2, 
4, 0), est = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), .Names = c("a", 
"b", "est"), row.names = c(NA, -10L), class = "data.frame") 

我想要做的,是检查的b值。如果b为0,我想将est设置为值a。据我所知df$est[df$b == 0] <- 23est的所有值设置为23,当时b==0。我不明白的是当条件为真时如何将est设置为值a。例如:

df$est[df$b == 0] <- (df$a - 5)/2.533 

给出了以下警告:

Warning message: 
In df$est[df$b == 0] <- (df$a - 5)/2.533 : 
    number of items to replace is not a multiple of replacement length 

有没有我可以通过相关的细胞,而不是向量的方法吗?

回答

53

既然你有条件索引df$est,你还需要有条件指数更换矢量df$a

index <- df$b == 0 
df$est[index] <- (df$a[index] - 5)/2.533 

当然,可变index只是暂时的,我用它来使代码多一点可读。你可以把它写在一个步骤:

df$est[df$b == 0] <- (df$a[df$b == 0] - 5)/2.533 

为了更好的可读性,您可以使用within:哪种方法

df <- within(df, est[b==0] <- (a[b==0]-5)/2.533) 

的结果,不管你选择:

df 
      a b  est 
1 11.77000 2 0.000000 
2 10.90000 3 0.000000 
3 10.32000 2 0.000000 
4 10.96000 0 2.352941 
5 9.90600 0 1.936834 
6 10.70000 0 2.250296 
7 11.43000 1 0.000000 
8 11.41000 2 0.000000 
9 10.48512 4 0.000000 
10 11.19000 0 2.443743 

正如其他人已经指出的,在您的示例中的替代解决方案是使用ifelse

11

这里有一种方法。 ifelse是向量化的,它检查所有行的零值为b,并用(a - 5)/2.53代替est(如果是这种情况)。

df <- transform(df, est = ifelse(b == 0, (a - 5)/2.53, est)) 
5

R-inferno或基本的R-文档将解释为什么使用df $ *不是这里最好的方法。在“[”的帮助页面中:“

”通过[索引]不同之处在于$不允许计算指数,而[[。x $ name等价于x [[“name”,exact = FALSE]]。另外,[[可以使用精确参数控制部分匹配行为。“

我推荐使用[row,col]表示法。例如:

Rgames: foo 
     x y z 
    [1,] 1e+00 1 0 
    [2,] 2e+00 2 0 
    [3,] 3e+00 1 0 
    [4,] 4e+00 2 0 
    [5,] 5e+00 1 0 
    [6,] 6e+00 2 0 
    [7,] 7e+00 1 0 
    [8,] 8e+00 2 0 
    [9,] 9e+00 1 0 
    [10,] 1e+01 2 0 
Rgames: foo<-as.data.frame(foo) 

Rgames: foo[foo$y==2,3]<-foo[foo$y==2,1] 
Rgames: foo 
     x y  z 
1 1e+00 1 0e+00 
2 2e+00 2 2e+00 
3 3e+00 1 0e+00 
4 4e+00 2 4e+00 
5 5e+00 1 0e+00 
6 6e+00 2 6e+00 
7 7e+00 1 0e+00 
8 8e+00 2 8e+00 
9 9e+00 1 0e+00 
10 1e+01 2 1e+01 
+0

这值得一给予好评,如果你第一次添加或者是链接到R-地狱页或者用'$'(或者理想情况下都是)来总结问题。 – Andrie

+0

+1虽然我认为在这种情况下'''运算符是完美无缺的。 (另外,我注意到,尽管你的警告你自己使用'''...) – Andrie

+0

@Andrie:是的,我在它的工作原理中使用过它(这不是那么有帮助:-))。 OP试图用它来定义哪些元素正在被执行,哪些是故障发生的地方。我只是用它来定义一个选择数据框元素的条件。但你知道这一点:-) –

24

尝试data.table:=操作:

DT = as.data.table(df) 
DT[b==0, est := (a-5)/2.533] 

它的快速和短暂。查看:=更多信息,这些链接的问题:

Why has data.table defined :=

When should I use the := operator in data.table

How do you remove columns from a data.frame

R self reference

+0

美丽,感谢参考+1的一切。 – PKumar

+0

非常有用的回应。如果使用这个,请确保注意DT不是data.table包中的函数,而是数据表对象的引用。 –