R检查一行字符串,如果相等,则分配相同的ID,减少耗时

时间:2016-11-11 12:24:21

标签: r performance time dataframe match

我对R很新,并且想知道这里是否有人能更好地解决我的问题,因为我太费时间了。我知道R不是“非循环友好”,所以我相信有更好的方法可以解决这个问题。

我有一个数据框,其中x是文本字符串,y是数字id:

x = c("a", "b", "c", "b", "a")
y = c(1,2,3,4,5)
df <- data.frame(x, y)

我希望找到列x中的所有匹配项,并为它们分配与y中第一个相同的数值。我用以下方法解决了这个问题:

library(foreach)
library(iterators)

for(i in 1:NROW(df)) {
  for(j in i:NROW(df)) {
    if(df$x[j] == df$x[i]){
      df$y[j] <- df$y[i]
    }
    j = j + 1
  }
  i = i + 1
}

问题是,我有一个相当大的数据集,这使得这个过程需要花费很多时间!希望这里的任何人都知道更少的时间消息!

2 个答案:

答案 0 :(得分:2)

如果您的数据集确实很大,那么data.table可能是最快的解决方案(参见基准here)。

library(data.table)
setDT(df)

df[, y := first(y), by = x]

答案 1 :(得分:1)

R喜欢矢量化代码,因此如果在循环中完成,算术运算和赋值等操作会很慢。例如,考虑以两种不同的方式将向量1,2,... 1,000,000分配给变量x

x <- 1:1e6

x <- numeric(x, 1e6) # initialise a numeric vector of length 1 million
for (i in 1:1e6) x[i] <- i

如果你试试这个,你会发现第二种方法需要更长的时间。

遇到问题,您希望按df$x中的值对数据进行分组,并将y的值替换为第一个元素

df.by <- by(df$x, function(d) transform(d, y = y[1]), data = df)

df的每个子集的第二列(基于df$x的子集)设置为等于其第一个元素。结果是

#df$x: a
#  x y
#1 a 1
#5 a 1
#------------------------------------------------------------
#df$x: b
#  x y
#2 b 2
#4 b 2
#------------------------------------------------------------
#df$x: c
#  x y
#3 c 3

要将这些组合回数据框,请使用df.new <- do.call(rbind, df.by)。此操作的一个(可能不需要的)副作用是它将改变行的顺序。

如果您是R的新手,请查看dplyr包,它具有流畅的学习曲线,并且易于编写和阅读语法。您想要做的只需几行即可完成。

library(dplyr)
df %>% group_by(x) %>% mutate(y = y[1])

会做到的!