【问题标题】:Compare corresponding columns of a data frame with list in R将数据框的相应列与 R 中的列表进行比较
【发布时间】:2020-10-17 07:34:33
【问题描述】:

我有一个包含用户数据的数据框

x <- data.frame("Address_line1" = c("461 road","PO Box 123","543 Highway"), 
                "City" = c("Dallas","Paris","New York" ), "Phone" = c("235","542","842"))
x
  Address_line1     City Phone
1      461 road   Dallas   235
2    PO Box 123    Paris   542
3   543 Highway New York   842

我有一个列表,其特征与数据框的顺序相同:

y = c("443 road","New york","842")
names(y) = colnames(x)

y

Address_line1          City         Phone 
   "443 road"    "New york"         "842"

我想遍历这个数据帧的每一行,用 y 计算 x 的对应字段的stringdist(),将这些值相加并得到每一行的总分。

例如,第一行的分数是:

row_1 = stringdist("461 road","443 road",method="lv") + stringdist("Dallas","New york",method="lv") + stringdist("235","842",method="lv")

row_1
[1] 13

同样,我想要数据框所有行的分数。这是我使用 for 循环编写的代码:

list_dist = rep(NA,0)

for(i in seq_len(nrow(x))){
    list_x = x[i,]
    sum=0
    for(j in seq_len(length(y))){
        sum = sum + stringdist(y[j],list_x[[j]],method = "lv")
    }
    #print(sum)
    list_dist[i] = sum
}


list_dist
[1] 13 18  8

我能够获得所需的输出,但问题在于计算时间。由于我的原始表包含约 100k 行和 10 列,因此代码运行需要近 30 分钟。我想知道是否有更有效的方法来做到这一点。

【问题讨论】:

  • 乍一看,如果你知道你最终输出的长度,你可以预先分配你的列表对象list_dist来加速for循环。否则你可以看看并行处理
  • y 始终是向量还是 data.frame?
  • @RuiBarradas y 也可以是一个 data.frame,在这种情况下,理想情况下,分数应该是一个大小为 nrow(y) x nrow(x) 的矩阵
  • 好的,你能更新y的例子吗?

标签: r dplyr tidyr stringdist


【解决方案1】:

这样更快。

rowSums(mapply(stringdist, y, x, method = 'lv'))
#[1] 13 18  8

编辑

这里是小x 的时间。这些函数使用包microbenchmark 计时。

Rahul <- function(){
  list_dist = rep(NA,0)

  for(i in seq_len(nrow(x))){
      list_x = x[i,]
      sum=0
      for(j in seq_len(length(y))){
          sum = sum + stringdist(y[j],list_x[[j]],method = "lv")
      }
      #print(sum)
      list_dist[i] = sum
  }
  list_dist
}
Rui <- function(){
  rowSums(mapply(stringdist, y, x, method = 'lv'))
}

library(microbenchmark)

for(i in 1:6) x <- rbind(x,x)
dim(x)
[1] 192  3

mb <- microbenchmark(
  Rui = Rui(),
  Rahul = Rahul()
)

print(mb, unit = 'relative', order = 'median')
#Unit: relative
#  expr      min       lq     mean   median       uq      max neval
#   Rui   1.0000   1.0000   1.0000   1.0000   1.0000   1.0000   100
# Rahul 141.5944 137.4175 133.4313 134.4163 132.2977 119.6172   100

差异已经是 magnutide 的 2 个数量级,并且会随着 nrow(x) 的增长而变大。

编辑 2

comment 出现问题后,下面的函数在y 是向量或data.frame 的情况下输出矩阵nrow(y) x nrow(x)

这个函数不是上面测速的函数Rui

rui <- function(x, y){
  out <- mapply(stringdistmatrix, y, x, MoreArgs = list(method = 'lv'), SIMPLIFY = FALSE)
  Reduce('+', out)
}

z <- data.frame(Address_line1 = c("443 road", "461 road"),
                City = c("New york", "London"), Phone = c("842", "524"))

rui(x, y)
#     [,1] [,2] [,3]
#[1,]   13   18    8

rui(x, z)
#     [,1] [,2] [,3]
#[1,]   13   18    8
#[2,]    9   17   19

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-14
    • 2018-03-14
    • 1970-01-01
    相关资源
    最近更新 更多