有条件地替换data.frame中的值


73

我试图了解如何在不使用循环的情况下有条件地替换数据框中的值。我的数据框的结构如下:

> 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] <- 23会将的所有值都设置est为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

有没有一种方法可以让我传递相关的单元格,而不是矢量?

Answers:


91

由于您要有条件地建立索引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


27

试试data.table:=运算符:

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

快速而简短。请参阅以下链接的问题,以获取有关以下内容的更多信息:=

为什么要定义data.table :=

我什么时候应该:=data.table

如何从 data.frame

R自参考


美丽,感谢您为所有内容提供+1。
PKumar,2014年

非常有用的回应。如果使用此功能,请确保注意DT不是data.table包中的函数,而是数据表对象的引用。
艾莉森·贝内特

20

这是一种方法。ifelse是向量化的,它将检查所有行的零值,如果是,则将其b替换为。est(a - 5)/2.53

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

8

另一种选择是使用case_when

require(dplyr)

mutate(df, est = case_when(
    b == 0 ~ (a - 5)/2.53, 
    TRUE   ~ est 
))

如果需要区分两种以上的情况,此解决方案将变得更加方便,因为它可以避免嵌套if_else构造。


7

R-地狱,或基本R-文件会为什么在这里使用DF $ *是不是最好的方法解释。从“ [”的帮助页面:

“用[进行索引是类似于原子向量,并选择指定元素的列表。[和$都选择列表中的单个元素。主要区别在于$不允许计算索引,而[[可以。x $ name等效于x [[“ name”,确切= 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

如果您首先添加一个链接到R-Inferno页面,或者总结问题所在$(或者最好同时总结两个问题),那么这是值得赞扬的。
Andrie

+1尽管我认为$在这种情况下,运算符非常好。(此外,我注意到,即使您发出警告,您还是要用$自己的
身体

@Andrie:是的,我在可行的地方使用了它(不是那有很多帮助:-))。OP试图使用它来定义要执行的操作,这是问题开始的地方。我只是用它来定义选择数据框元素的条件。但是您知道的是:-)
卡尔·威索夫特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.