【问题标题】:How to iterate and test columns of a data frame in R faster?如何更快地迭代和测试 R 中数据框的列?
【发布时间】:2019-02-20 00:21:05
【问题描述】:

我在 R 中有一个数据框,其中包含 2 个变量:a 和 b。

我想逐行测试变量a是否包含模式'OK'。

如果是TRUE,我想把变量a和变量b的内容倒置在同一行。

以下代码正在运行:

for(i in 1:nrow(dataframe)){
  if(!is.na(grep('OK', dataframe$a[i])[1])){
    b = dataframe$b[i]
    dataframe$b[i] <- dataframe$a[i]
    dataframe$a[i] <- b
  }
}

我想知道是否有更好的方法来获得相同的结果,但速度更快?

【问题讨论】:

  • 不要在循环中使用ifelse,除非您在列上循环。 ifelse 函数已经像一个向量参数的循环一样。投票结束本质上是一个错字。
  • 感谢指正。我更改了代码。

标签: r dataframe loops


【解决方案1】:

通过在 R 中使用矢量化函数,您可以在一个函数调用中测试所有行。您可以在下面的示例中看到我的代码快了 50 倍。

在这种情况下,if_else 是 ifelse 的矢量化版本,str_detect 是 grep 的矢量化版本。 tidyverse 包和管道提供了函数 select 和 mutate,这使得使用矢量化函数操作数据帧变得容易。

library(tidyverse)

n <- 10000
sampledata <- data.frame(aa=rbinom(n, 1, 0.5), b = rep("bvalue", n), stringsAsFactors = FALSE) %>% 
  mutate(a = if_else(aa == 0, "nothing", "OK")) %>% 
  select(a, b, -aa)

yourcode <- function(sampledata) {  
  newdata <- sampledata
  for(i in 1:nrow(sampledata)){
    if(!is.na(grep('OK', sampledata$a[i])[1])){
      b <- sampledata$b[i]
      newdata$b[i] <- sampledata$a[i]
      newdata$a[i] <- b
    }
  }
  return(newdata)
}

# using vectorized functions and tidyverse will make your code faster

mycode <- function(sampledata) {
  newdata <- sampledata %>% mutate(new_b = if_else(str_detect(a, "OK"), a, b),
                                   new_a = if_else(str_detect(a, "OK"), b, a)) %>%
    select(-a, -b, a = new_a, b = new_b)
  return(newdata)
  }

system.time(yourcode(sampledata))
#>    user  system elapsed 
#>    1.46    0.03    1.56
system.time(mycode(sampledata))
#>    user  system elapsed 
#>    0.03    0.00    0.03

由reprex package (v0.2.1) 于 2019 年 2 月 20 日创建

【讨论】:

猜你喜欢
  • 2022-01-16
  • 1970-01-01
  • 2020-06-05
  • 2021-07-09
  • 2020-06-10
  • 2021-09-17
  • 2014-04-27
  • 2021-09-30
  • 2021-11-30
相关资源
最近更新 更多