【问题标题】:Replacing subsets in R with Tidyverse用 Tidyverse 替换 R 中的子集
【发布时间】:2023-04-07 03:35:01
【问题描述】:

如何用Tidyverse 替换R 中子集的值?

cars数据为例,如果我想把小于30的speed全部改成0,可以使用下面的命令:

 cars[cars["speed"] < 30,] <- 0

使用Tidyverse,可以生成具有更多可读命令的相同子集:

 cars %>% filter(speed < 30) %>% mutate(speed =0)

然而,这改变了我们从cars 中提取的数据子集,而不是cars 中的观察值。

我可能遗漏了一些明显的东西,但有没有一种直观的方法可以用Tidyverse 做同样的事情?虽然cars[cars["speed"] &lt; 30,] &lt;- 0 在大多数情况下都能正常工作,但当一个人需要满足 5 个以上的条件时,它就会变得非常笨拙。

【问题讨论】:

  • 我认为这可能是您不应该尝试使所有内容“整洁”的情况。 replace 就是 x[list] &lt;- values,这与你所做的差不多,而且它是 - IMO - 具有可读性和抽象性。

标签: r tidyverse


【解决方案1】:

你可以使用replace函数:

cars %>% mutate(speed = replace(speed, speed < 30, 0))

ifelse 条件也可以:

cars %>% mutate(speed = ifelse(speed < 30, 0, speed))

我在一百万行的数据帧上对此进行了测试,replace 的运行时间大约是ifelse 的八分之一。

library(microbenchmark)

set.seed(2)
dat = data.frame(x=runif(1e6, 0, 1000), y=runif(1e6, 0, 1000))

microbenchmark(
  replace=dat %>% mutate(x=replace(x, x<200, 0)),
  ifelse=dat %>% mutate(x=ifelse(x<200, 0, x)),
  if_else=dat %>% mutate(x=if_else(x<200, 0, x)),
  times=100
)
Unit: milliseconds
    expr       min       lq      mean   median        uq      max neval cld
 replace  8.352943  9.55682  18.16755 11.45507  15.33215 224.8759   100 a  
  ifelse 71.782371 87.37754 165.95928 95.12722 262.73016 287.3633   100   c
 if_else 39.947845 47.83934  88.72291 51.99449  59.76760 251.0381   100  b

【讨论】:

  • 真正引人注目的比较。想知道如果你使用 dplyr 命令if_else 会是什么样子。它应该比基础ifelse快得多...
  • 查看更新时间。 if_elseifelse 快,但比 replace 慢。
  • 如果mutate 有某种%&lt;&gt;% 类似物就好了,例如cars %&gt;% mutate(speed %=% replace(., . &lt; 30, 0))(我知道这很难实现的原因有很多,但仍然......
猜你喜欢
  • 2019-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-09
  • 2020-07-02
  • 1970-01-01
  • 2016-11-29
  • 1970-01-01
相关资源
最近更新 更多