使用另一个数据框作为地图替换数据框中的列?

时间:2016-10-17 13:00:28

标签: r

在我的具体情况中,我有两个数据框:

> a
         column
1     red apple
2       red car
3  yellow train
4        random
5 random string
6    blue water
7         thing

> map
       x     y
1    red color
2   blue color
3 yellow color
4 random other
5  thing other

我想要的结果是:

> a
         column
1         color
2         color
3         color
4         other
5         other
6         color
7         other

我知道这篇文章给出了使用merge Replacing values in data frame column using another data frame的示例。但就我而言,这方面略有不同:

  1. 我想检查列x的子字符串键是否包含在。
  2. 的任何“列”中
  3. 来自的地图数据很多 - >单一映射。
  4. 我如何写一些能够有效地为我做这件事的东西?实际上两个数据框架更大。 A是30k行,地图是30x2

    编辑:子字符串可以从“列”开始,而不一定是第一个字

2 个答案:

答案 0 :(得分:1)

可重复的例子:

a <- data.frame(column=c('red apple', 'red car', 'yellow train', 'random', 'random string', 'blue water', 'thing'), stringsAsFactors=F)
map <- data.frame(x=c('red', 'blue', 'yellow', 'random'), y=c('color', 'color', 'color', 'other'))

有几个选择。我能想到两个(我相信还有更多),我会告诉你如何计时他们来比较他们的表现。您可能必须尝试自己的特定数据的时间,因为哪种方法最快可能会改变,具体取决于例如map$xa的比较大小,或amap的大小。

  • 如果您知道第一个单词上的匹配(如果有)总是,那么您可以跳过正则表达式并使用strsplit来抓取第一个单词。
  • 否则,正则表达式可以在这里帮助你(并且有各种方法来执行正则表达式。)
  • 注意pmatch在这里不会真正起作用,因为你试图将更长的字符串与更短的字符串匹配。
  • data.table是快速处理大数据的常用方法。我认为正则表达式可能是这里的限制因素,所以我不确定你会以这种方式加速。

# rbenchmark library to compare times
library(rbenchmark)
benchmark(firstword={
  # extract first word; match exactly against the map
  # probably fastest; but "dumbest" unless you know the first word
  #  is always the match
  firstword <- vapply(a$column, function (x) strsplit(x, ' ')[[1]][1], '', USE.NAMES=F) 
  out.firstword <<- map$y[match(firstword, map$x)]
},
regex = {
  # regex option: find the matching word, then use `match`
  #  will have problems if any of map$x has regex special characters.
  regex <- sprintf('^.*\\b(%s)\\b.*$', paste(map$x, collapse='|')) # ^.*\b(red|blue|yellow|random)\b.*$  
  out.regex <- map$y[match(gsub(regex, '\\1', a$column), map$x)]
},
replications=100)

# check we at least agree on the output and get the expected output
all.equal(out.regex, out.firstword)
all.equal(as.character(out.regex), c('color', 'color', 'color', 'other', 'other', 'color', NA))

请注意,如果您对大数据进行基准测试,则可能希望减少重复次数!你不想坐等几年...... 另请注意,最后一行返回“NA”而不是其他行,因为字符串“thing”与地图中的任何内容都不匹配。

返回

       test replications elapsed relative user.self sys.self user.child sys.child
1 firstword          100   0.010    1.111         0        0          0         0
2     regex          100   0.009    1.000         0        0          0         0

因此,对于您的特定示例数据,正则表达式方法更快 - 但如前所述,它将全部取决于您的特定数据[此示例的性质是数据集很小,所以一切都快于其他]所以你的里程可能会有所不同。

答案 1 :(得分:0)

已编辑:反映来自mathematical.coffee的评论 已编辑:在匹配时切换订单

首先,我们需要清理数据帧,使其与预期的字段匹配。所以像a$column1 <- gsub("red.+","red",a$column)之类的东西,然后冲洗并重复其余部分。我不知道如何匹配&#34;其他&#34;类别......必须手动完成。

一旦你有了正确的名字,match就可以在这里运作良好:

您应该使用以下内容获取所需的结果:map$y[match(a$column1,map$x)]。内部部分进行匹配,map$y部分为您提供所需的属性。