-3

我有两个数据框,如下所示。DF1 有点凌乱(如下所示)将 DF2 中的多个值合并到一列中。

DF1
编号 价值
1 1ABCD2EFGH3IJKL
2 1ABCD2EFGH3IJKL/7MLPO0OKMN8MNBV
3 3ABCD4EFGH5IJKL
4 3ABCD4EFGH5IJKL/1ABCD2EFGH3IJKL
5 7MLPO0OKMN8MNBV/9IUYT7HGFD3LKJH
DF2
编号 价值
1 1ABCD2EFGH3IJKL
2 3ABCD4EFGH5IJKL
3 6PQRS7TUVW8XYZA
4 5FGHI9XUZX1RATP
5 9AGTY6UGFW0AAUU
6 6TEYD7RARA8MHAT
7 9IUYT7HGFD3LKJH

我想在两个数据集中使用值列进行查找。这是我想要完成的。

i) 对于 DF1 中的第 1 行和第 3 行,它是在 DF2 中的简单查找。我希望代码返回那些查找的值。
ii) 对于 DF1 中的第 3 行,只有字符串的第一部分与 DF2 中的值匹配。我希望代码只返回第一部分。
iii) 对于 DF1 中的第 4 行,字符串中的两个部分都与 DF2 中的值匹配。在这种情况下,我希望保留匹配的字符串的第一部分
iv) 对于第 5 行,字符串的第二部分与 DF2 中的值匹配。我希望代码返回字符串的第二部分。

我在第一个数据集中有大约 47000 行,在第二个数据集中有超过 300,000 行,当然这两个数据集中还有其他列。我已经使用 str_split/str_match 以多种方式进行了尝试,但无法完成我想要的。每一个建议都值得赞赏。我其余的编码都在 R 中。

谢谢你

4

2 回答 2

0

第一步是tidyr::separate()在“/”处访问您的 DF1。然后我用;dplyr::case_when()查看 DF2 中列出的第一个项目是否匹配%in%;如果没有,则检查第二个。我曾经dplyr::mutate()将结果附加到 DF1 下dat

library(dplyr)
library(tidyr)

DF1 <- data.frame("SRNo." = 1:5, Value = c("1ABCD2EFGH3IJKL","1ABCD2EFGH3IJKL/7MLPO0OKMN8MNBV","3ABCD4EFGH5IJKL","3ABCD4EFGH5IJKL/1ABCD2EFGH3IJKL","7MLPO0OKMN8MNBV/9IUYT7HGFD3LKJH"), stringsAsFactors = F) %>% tbl_df()

DF2 <- data.frame("SRNo." = 1:7, Value = c("1ABCD2EFGH3IJKL","3ABCD4EFGH5IJKL","6PQRS7TUVW8XYZA","5FGHI9XUZX1RATP","9AGTY6UGFW0AAUU","6TEYD7RARA8MHAT","9IUYT7HGFD3LKJH"), stringsAsFactors = F) %>%tbl_df()

DF1 %>%
  separate(Value, c("Value1", "Value2"), sep = "/")  %>%
  mutate(dat = case_when(
    Value1 %in% DF2$Value ~ Value1,
    Value2 %in% DF2$Value ~ Value2,
    TRUE ~ NA_character_
  ))

# # A tibble: 5 x 4
#   SRNo. Value1          Value2          dat            
#   <int> <chr>           <chr>           <chr>          
# 1     1 1ABCD2EFGH3IJKL NA              1ABCD2EFGH3IJKL
# 2     2 1ABCD2EFGH3IJKL 7MLPO0OKMN8MNBV 1ABCD2EFGH3IJKL
# 3     3 3ABCD4EFGH5IJKL NA              3ABCD4EFGH5IJKL
# 4     4 3ABCD4EFGH5IJKL 1ABCD2EFGH3IJKL 3ABCD4EFGH5IJKL
# 5     5 7MLPO0OKMN8MNBV 9IUYT7HGFD3LKJH 9IUYT7HGFD3LKJH
于 2018-09-25T08:21:22.887 回答
0

数据表解决方案

df1 <- read.table(text="SRNo.      Value
                  1      1ABCD2EFGH3IJKL
                  2      1ABCD2EFGH3IJKL/7MLPO0OKMN8MNBV
                  3      3ABCD4EFGH5IJKL
                  4      3ABCD4EFGH5IJKL/1ABCD2EFGH3IJKL
                  5      7MLPO0OKMN8MNBV/9IUYT7HGFD3LKJH", header = T, stringsAsFactors = F)

df2 <- read.table( text = "SRNo.   Value
                   1   1ABCD2EFGH3IJKL
                   2   3ABCD4EFGH5IJKL
                   3   6PQRS7TUVW8XYZA
                   4   5FGHI9XUZX1RATP
                   5   9AGTY6UGFW0AAUU
                   6   6TEYD7RARA8MHAT
                   7   9IUYT7HGFD3LKJH", header = T, stringsAsFactors = F )

library( data.table )
setDT(df1)[, c( "Value1", "Value2" ) := tstrsplit( Value, "/", fixed = TRUE)]
setDT(df2)

resultv1 <- df2[ df1, on = c( Value = "Value1"), nomatch = 0L ]
resultv2 <- df2[ df1, on = c( Value = "Value2"), nomatch = 0L ]

result <- rbindlist( list( resultv1, resultv2 ) )[!duplicated( i.SRNo.)]

将其与@Paul 的解决方案进行基准比较显示出相似的运行时间(约 2.5 毫秒)。但 data.table 有时在更大的数据集上让我感到惊讶。

如果内存成为问题,您可以一次性完成所有操作:

rbindlist( list( setDT(df2)[ setDT(df1)[, c( "Value1", "Value2" ) := tstrsplit( Value, "/", fixed = TRUE)], 
                               on = c( Value = "Value1"), nomatch = 0L ], 
                   setDT(df2)[ setDT(df1)[, c( "Value1", "Value2" ) := tstrsplit( Value, "/", fixed = TRUE)], 
                               on = c( Value = "Value2"), nomatch = 0L ] ) )[!duplicated( i.SRNo.)]
于 2018-09-25T08:31:35.190 回答