【问题标题】:Conditional replacement of values in a data.frame有条件地替换 data.frame 中的值
【发布时间】:2012-01-03 02:22:33
【问题描述】:

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

> 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

有没有办法可以传递相关的单元格,而不是向量?

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      试试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

      【讨论】:

      • 美丽,感谢您的参考 +1 一切。
      • 非常有用的回复。如果使用这个,一定要注意DT不是data.table包中的函数,而是对数据表对象的引用。
      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        另一种选择是使用case_when

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

        如果需要区分超过 2 个案例,此解决方案会变得更加方便,因为它可以避免嵌套的 if_else 构造。

        【讨论】:

          【解决方案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
          

          【讨论】:

          • 如果您首先添加指向 R-Inferno 页面的链接,或者使用 $(或理想情况下两者)总结问题,这值得一票。
          • +1 虽然我认为 $ 运算符在这种情况下非常好。 (另外,我注意到尽管您发出警告,但您自己使用$...)
          • @Andrie:是的,我在它工作的地方使用了它(并不是说这有很大帮助:-))。 OP 试图用它来定义正在对哪些元素进行操作,这就是问题开始的地方。我只是用它来定义选择数据框元素的条件。但你知道:-)
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-12-24
          • 2021-10-15
          • 2021-06-11
          • 2013-07-13
          • 2019-04-08
          • 1970-01-01
          相关资源
          最近更新 更多