【问题标题】:Looking up values from another dataframe in r从 r 中的另一个数据框中查找值
【发布时间】:2018-07-13 15:09:46
【问题描述】:

我有一个名为 df 的大型数据框,带有一些 ID。

我有另一个数据框 (id_list),其中包含一组匹配的 ID 及其与每个 ID 相关的特征。 ID 在两个数据帧中不是按顺序排列的。

实际上,我想从较大的数据帧df 查找id_list,并将DisplayType 两列添加到当前数据帧df

有许多令人困惑的例子。什么可能是最有效的方法。我尝试使用 match()%in% 并且失败了。

这是一个可重现的例子。

df <- data.frame(Feats = matrix(rnorm(20), nrow = 20, ncol = 5), ID = sample.int(10, 10))

id_list <- data.frame(ID = sample.int(10,10),
           Display = sample(c('clear', 'blur'), 20, replace = TRUE),
           Type = sample(c('red', 'green', 'blue', 'indigo', 'yellow'), 20, replace = TRUE))

           Feats.1     Feats.2     Feats.3     Feats.4     Feats.5 ID
1   3.14944573 -0.52285062  3.14944573 -0.52285062  3.14944573  2
2  -0.41096007  0.38256691 -0.41096007  0.38256691 -0.41096007  1
3   0.03629351 -0.02514005  0.03629351 -0.02514005  0.03629351  7
4   0.91257290  1.35590761  0.91257290  1.35590761  0.91257290  5
5  -0.26927311 -2.10213773 -0.26927311 -2.10213773 -0.26927311  3
6   3.14944573 -0.52285062  3.14944573 -0.52285062  3.14944573  4
7  -0.41096007  0.38256691 -0.41096007  0.38256691 -0.41096007 10
8   0.03629351 -0.02514005  0.03629351 -0.02514005  0.03629351  6
9   0.91257290  1.35590761  0.91257290  1.35590761  0.91257290  8
10 -0.26927311 -2.10213773 -0.26927311 -2.10213773 -0.26927311  9

  ID Display   Type
1   6   clear indigo
2   1    blur   blue
3   7   clear    red
4   4   clear    red
5   3    blur    red
6  10   clear yellow
7   2   clear   blue
8   8    blur  green
9   5   clear   blue
10  9   clear  green

生成的结束 df 的大小应为 [20 x 8]。

【问题讨论】:

标签: r lookup data-manipulation


【解决方案1】:

您可以使用基础 R 中的 mergedplyr 中的 left_join 来轻松完成此操作。 (还有data.table::merge,也许其他人可以给出答案。)如果数据框中的条目没有相应的 ID,您可能需要采取措施确保不会丢失任何数据在查找中。如果不是这种情况,您可以将merge 中的all.x 更改为false 或null,或者从left_join 切换为inner_join。为了说明,我在数据中添加了一个虚拟行,其 ID 在查找表中不存在。

df <- data.frame(Feats = matrix(rnorm(10), nrow = 5, ncol = 5), ID = sample.int(10, 10))
dummy <- df[1, ]
dummy$ID <- 12
df <- rbind(dummy, df)

id_list <- data.frame(ID = sample.int(10,10),
                      Display = sample(c('clear', 'blur'), 10, replace = TRUE),
                      Type = sample(c('red', 'green', 'blue', 'indigo', 'yellow'), 10, replace = TRUE))

使用merge,您可以将by 设置为两个数据框中要连接的列名,或者将by.xby.y(如果它们的名称不同)设置为。 all.x = T 会将所有观察结果保留在第一个数据帧中,即使它们与第二个数据帧中的观察结果不匹配。

merged1 <- merge(df, id_list, by = "ID", sort = F, all.x = T)
merged1
#>    ID     Feats.1    Feats.2     Feats.3    Feats.4     Feats.5 Display
#> 1  10 -1.44053344  1.0086988 -1.44053344  1.0086988 -1.44053344   clear
#> 2   5  0.99220217 -0.3125813  0.99220217 -0.3125813  0.99220217   clear
#> 3   2  1.03881289  1.1277627  1.03881289  1.1277627  1.03881289   clear
#> 4   7 -0.01678186 -0.1519029 -0.01678186 -0.1519029 -0.01678186   clear
#> 5   4  0.07130125  1.1715833  0.07130125  1.1715833  0.07130125   clear
#> 6   6 -1.44053344  1.0086988 -1.44053344  1.0086988 -1.44053344   clear
#> 7   8  0.99220217 -0.3125813  0.99220217 -0.3125813  0.99220217    blur
#> 8   3  1.03881289  1.1277627  1.03881289  1.1277627  1.03881289   clear
#> 9   1 -0.01678186 -0.1519029 -0.01678186 -0.1519029 -0.01678186   clear
#> 10  9  0.07130125  1.1715833  0.07130125  1.1715833  0.07130125   clear
#> 11 12 -1.44053344  1.0086988 -1.44053344  1.0086988 -1.44053344    <NA>
#>      Type
#> 1  indigo
#> 2  yellow
#> 3    blue
#> 4  indigo
#> 5  yellow
#> 6  indigo
#> 7   green
#> 8     red
#> 9     red
#> 10   blue
#> 11   <NA>

dplyr::left_join 保留第一个数据帧中的所有观察结果,并合并第二个数据帧中的任何匹配结果。

joined <- dplyr::left_join(df, id_list, by = "ID")
head(joined)
#>       Feats.1    Feats.2     Feats.3    Feats.4     Feats.5 ID Display
#> 1 -1.44053344  1.0086988 -1.44053344  1.0086988 -1.44053344 12    <NA>
#> 2 -1.44053344  1.0086988 -1.44053344  1.0086988 -1.44053344 10   clear
#> 3  0.99220217 -0.3125813  0.99220217 -0.3125813  0.99220217  5   clear
#> 4  1.03881289  1.1277627  1.03881289  1.1277627  1.03881289  2   clear
#> 5 -0.01678186 -0.1519029 -0.01678186 -0.1519029 -0.01678186  7   clear
#> 6  0.07130125  1.1715833  0.07130125  1.1715833  0.07130125  4   clear
#>     Type
#> 1   <NA>
#> 2 indigo
#> 3 yellow
#> 4   blue
#> 5 indigo
#> 6 yellow

reprex package (v0.2.0) 于 2018 年 7 月 13 日创建。

【讨论】:

  • 它适用于此,但我实际的df id_list 对同一个 ID 字段有多个值。例如。 ID == 2 有 100 行。所以它的作用是,它加入了 df 并导致新的 df 是原始 df 的两倍。抱歉,如果我没有正确传达这一点。
  • 是的,这不在最初的问题中。如果您在数据和 ID 查找中多次使用相同的 ID,您打算如何区分它们?
【解决方案2】:

如果您可以确保数据框 df 和 id_list 具有相同的 ID(只是顺序不同),那么您可以尝试以下方法:

# define new data frame
orderd_id_list <- data.frame()

# loop over rows of df (get new ID each round)
for (i in seq(nrow(df))) {
  # find the row in id_list where the ID "id_list$ID" is identical to
  # current ID in df for this round "df$ID[i]"
  new_row <- id_list[id_list$ID == df$ID[i],]
  # add new row to orderd_id_list
  orderd_id_list <- rbind(orderd_id_list, new_row)
}

# merge (add columns) Display and Type columns of new orderd data frame with df
merged_df <- cbind(Display = orderd_id_list$Display, Type = orderd_id_list$Type, df)

在 R 中使用 for 循环并不是最佳做法,但如果您的数据框不太大,那就没问题了。

基本上,您创建 id_list 的新有序(基于 df$ID 排序)副本,然后将其与 df 合并。

希望对你有帮助:)

【讨论】:

  • 我不认为有一个令人信服的理由使用 for 循环,因为 R 旨在执行向量操作,并且基础 R 中存在执行此操作的函数 (merge)。对于 ID 在一个数据帧中但不在另一个数据帧中的情况,有什么故障保护措施?
  • 是的,你是对的。在 R 中使用 for 循环并没有什么特别的理由。我只是想写一个简短的建议作为答案。
猜你喜欢
  • 2020-04-21
  • 1970-01-01
  • 2019-04-04
  • 2018-09-11
  • 2017-01-20
  • 2021-04-22
  • 2021-09-19
  • 1970-01-01
  • 2022-06-27
相关资源
最近更新 更多