【问题标题】:R: find value in a dataframe based on value in another dataframeR:根据另一个数据帧中的值查找数据帧中的值
【发布时间】:2018-06-13 10:48:16
【问题描述】:

这个问题与here 提出的问题类似,但还有另一列在起作用。

我有两个 R 数据框:

df_1 有四列。 Name1 具有关联类型 Type1。也就是说,A1 属于 T1 类型,A4 属于 T3 类型,等等。最后一列只是名称。

ID1     Name1     Type1     Name2
1       A1         T1        B1
2       A2         T2        B2
3       A3         T1        B3_a
4       A4         T3        B4_a  

我有第二个数据框,其中包含Name2 中可能出现的所有名称的列表。

df_2:

NameBank     TypeBank
A1             T1
A2             T2
A3             T1
A4             T3
B1             T1
B2             T4
B3             T2
B4             T3

在 df_1 中,Name2 的字符数可能比 df_2 中 NameBank 中的关联值多。

我想在 df_2 中找到与 df_1 中的 Name2 关联的 TypeBank 值。也就是说,我希望最终的数据框看起来像这样:

ID1     Name1     Type1     Name2     Type2
1       A1         T1        B1       T1
2       A2         T2        B2       T4
3       A3         T1        B3_a     T2
4       A4         T3        B4_a     T3

第一个数据帧中有数万个条目,第二个数据帧有几百个条目。我怎样才能在 R 中有效地做到这一点?

【问题讨论】:

  • NameBank 的所有值是否始终与Name2 值的前 2 个字符匹配?
  • @rosscova 好问题:不。
  • 是否总是在末尾添加任何额外字符,并以下划线开头?如果是这样,下面@missuse 的答案应该有效。
  • 也是一个好问题 - 我的 MWE 从外观上看有点误导人,我很抱歉!人物可以是任何东西。开头总是会包含一个匹配项:也就是说,我可以使用 B3axyzlmnop、B3ThisisaWord 或带有空格的“B3 something else”来代替 B3_a。
  • NameBank 值是否总是 2 个字符长?

标签: r


【解决方案1】:

使用 dplyr 的一种方法:

library(dplyr)

t1 %>%
  mutate(Name3 = sub("_[a-z]$", "", Name2)) %>%
  left_join(t2, by = c("Name3" = "NameBank")) %>%
  select(-Name3)

#output
  ID1 Name1 Type1 Name2 TypeBank
1   1    A1    T1    B1       T1
2   2    A2    T2    B2       T4
3   3    A3    T1  B3_a       T2
4   4    A4    T3  B4_a       T3

首先我们通过删除_后跟字符串末尾的任何字母来生成一个新变量,然后通过新变量将两个数据框连接起来。

根据Name2 和NameBank 之间的关系,其他一些字符串操作可能更适合。

数据:

t1 <- read.table(text = "ID1     Name1     Type1     Name2
1       A1         T1        B1
2       A2         T2        B2
3       A3         T1        B3_a
4       A4         T3        B4_a", header = T)


t2 <- read.table(text = "NameBank     TypeBank
A1             T1
A2             T2
A3             T1
A4             T3
B1             T1
B2             T4
B3             T2
B4             T3", header = T)

编辑:也许对您的问题更好的解决方案是使用charmatch,它会在第二个参数中寻找其第一个参数的元素的匹配项。:

chrs <- charmatch(t2$NameBank, t1$Name2)
cbind(
  t1[chrs[!is.na(chrs)],],
  t2[which(!is.na(chrs)),]
)
#output
  ID1 Name1 Type1 Name2 NameBank TypeBank
1   1    A1    T1    B1       B1       T1
2   2    A2    T2    B2       B2       T4
3   3    A3    T1  B3_a       B3       T2
4   4    A4    T3  B4_a       B4       T3

chrs
[1] NA NA NA NA  1  2  3  4

所以NameBank 的第5 个元素匹配Name2 的第一个元素等。然后使用该信息适当地绑定两个数据帧。

【讨论】:

    【解决方案2】:

    由于您要在字符串的开头搜索匹配项,但您没有任何符合逻辑的“正则表达式”规则可循,不妨使用for 循环。

    我们遍历t2$NameBank 的每个值,找到t1 中NameBank 值与开头匹配的所有行(与给定NameBank 值的长度相同),并将它们替换为对应的@ 987654326@值。

    t1$Type2 <- NA_character_
    for( row in seq_len( nrow( t2 ) ) ) {
        t1$Type2[ substr( t1$Name2, 0, nchar( t2$NameBank[row] ) ) == t2$NameBank[row] ] <- t2$TypeBank[row]
    }
    

    这给了

    > t1
      ID1 Name1 Type1 Name2 Type2
    1   1    A1    T1    B1    T1
    2   2    A2    T2    B2    T4
    3   3    A3    T1  B3_a    T2
    4   4    A4    T3  B4_a    T3
    

    这是一个for 循环,因此在大型数据集上可能会很慢,但在您的情况下似乎是必要的。

    【讨论】:

      猜你喜欢
      • 2021-01-08
      • 2021-01-26
      • 2020-06-08
      • 2018-01-10
      • 1970-01-01
      • 2021-08-18
      • 1970-01-01
      • 2022-01-20
      • 1970-01-01
      相关资源
      最近更新 更多