【问题标题】:Join two data frames by searching & matching strings通过搜索和匹配字符串连接两个数据框
【发布时间】:2017-01-28 06:19:02
【问题描述】:

我有两个数据框

df1

+-------+---------+  
|   Id  |  Title  |
+-------+---------+  
|   1   |   AAA   |
|   2   |   BBB   |
|   3   |   CCC   |
+-------+---------+

df2

+-------+---------------+------------------------------------+
|   Id  |      Sub      |               Body                 |
+-------+---------------+------------------------------------+  
|   1   |   some sub1   | some mail body AAA some text here  |
|   2   |   some sub2   | some text here BBB continues here  |
|   3   |   some sub3   | some text AAA present here         |
|   4   |   some sub4   | AAA string is present here also    |
|   5   |   some sub5   | CCC string is present here         |
+-------+---------------+------------------------------------+

我想将 df1 中的 Titledf2Body 列匹配,
如果 Body 列中存在标题字符串,则应连接两行,输出数据框应如下所示:

df3

+----------+---------------+------------------------------------+
|   Title  |      Sub      |               Body                 |
+----------+---------------+------------------------------------+  
|   AAA    |   some sub1   | some mail body AAA some text here  |
|   BBB    |   some sub2   | some text here BBB continues here  |
|   AAA    |   some sub3   | some text AAA present here         |
|   AAA    |   some sub4   | AAA string is present here also    |
|   CCC    |   some sub5   | CCC string is present here         |
+----------+---------------+------------------------------------+

【问题讨论】:

  • 我的回答对你有用吗?
  • @DAXaholic,感谢您的回复。您的示例与您的代码完美配合,但是当我尝试添加我的实际数据时,我收到以下错误。 Error in grepl(df1$title[idx], df2$body) : invalid 'pattern' argument。对不起,我在我的问题中又错过了一件事情,在 Title 我有像“AAA BB”这样的字符串,而不仅仅是“AAA”。我用数据“AAA BB”尝试了你的代码,它给出了以下错误Error in data.frame(..., check.names = FALSE) : arguments imply differing number of rows: 1, 0
  • 当我们不能假设每个标题都匹配某些行时,我用另一种方法更新了我的答案 - 希望有帮助

标签: r dataframe


【解决方案1】:

一个解决方案可能看起来像这样,尽管更有经验的 R 用户可能会想出更好的答案

# set up test data
df1 <- data.frame(stringsAsFactors = F,
                  id = 1:3,
                  title = c('AAA', 'BBB', 'CCC'))
df2 <- data.frame(stringsAsFactors = F,
                  id = 1:5,
                  sub = c('some sub1', 'some sub2', 'some sub3', 'some sub4', 'some sub5'),
                  body = c('some mail body AAA some text here',
                           'some text here BBB continous here',
                           'some text AAA present here',
                           'AAA string is present here also',
                           'CCC string is present here'))

# join data frames
df.list <- lapply(1:nrow(df1), function (idx) cbind(title=df1[idx,2], df2[grepl(df1$title[idx], df2$body), 2:3]))
do.call('rbind', df.list)

这将导致以下输出

  title       sub                              body
1   AAA some sub1 some mail body AAA some text here
3   AAA some sub3        some text AAA present here
4   AAA some sub4   AAA string is present here also
2   BBB some sub2 some text here BBB continous here
5   CCC some sub5        CCC string is present here

因评论而更新:

如果我们不能依赖每个标题将匹配df2 中的某些行这一事实,那么您可能想要做这样的事情

# set up test data
df1 <- data.frame(stringsAsFactors = F,
                  id = 1:4,
                  title = c('AAA', 'AAA BB', 'BBB', 'CCC'))
df2 <- data.frame(stringsAsFactors = F,
                  id = 1:5,
                  sub = c('some sub1', 'some sub2', 'some sub3', 'some sub4', 'some sub5'),
                  body = c('some mail body AAA some text here',
                           'some text here BBB continous here',
                           'some text AAA present here',
                           'AAA string is present here also',
                           'CCC string is present here'))

MergeByTitle <- function(title.idx) {
  df2.hits <- df2[grepl(df1$title[title.idx], df2$body), 2:3]
  if (nrow(df2.hits) > 0)
    cbind(title=df1[title.idx,2], df2.hits)
}

# join data frames
df.list <- lapply(1:nrow(df1), MergeByTitle)
do.call('rbind', df.list)

【讨论】:

  • 非常感谢,它有帮助,这正是我想要的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-06
  • 2021-09-10
  • 1970-01-01
  • 1970-01-01
  • 2012-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多