【问题标题】:Data.frame transform data with criteria from another data.frame like Excel "criteria table"Data.frame 使用来自另一个 data.frame(如 Excel“标准表”)的标准转换数据
【发布时间】:2020-04-22 21:10:57
【问题描述】:

我有 data.frame df1 和一个 data.frame df2。如何使用 df2 将 df1 变异/转换为 merged data.frame 其中:如果 df1$id >= df2$start 和 name 列将填充 df2$name 上的值。

df1 = data.frame(id = 1:10, c = letters[1:10])
df2 = data.frame(name = LETTERS[1:3], start = c(2, 5, 8), end = c(4,7, 9))
merged = data.frame(id = df1$id, c = df1$c, name = c(NA, "A", "A", "A", "B", "B", "B", "C", "C", NA) )

视觉上:

> df1
   id c
1   1 a
2   2 b
3   3 c
4   4 d
5   5 e
6   6 f
7   7 g
8   8 h
9   9 i
10 10 j
> df2
  name start end
1    A     2   4
2    B     5   7
3    C     8   9
> merged
   id c name
1   1 a <NA>
2   2 b    A
3   3 c    A
4   4 d    A
5   5 e    B
6   6 f    B
7   7 g    B
8   8 h    C
9   9 i    C
10 10 j <NA>

【问题讨论】:

    标签: r dataframe tidyverse


    【解决方案1】:

    我们可以在data.table 中使用非等值连接,并在满足条件连接的地方分配一个具有“name”对应值的新列

    library(data.table)
    setDT(df1)[df2, cn := name, on = .(id > start, id <= end)]
    df1
    #    id c   cn
    # 1:  1 a <NA>
    # 2:  2 b <NA>
    # 3:  3 c    A
    # 4:  4 d    A
    # 5:  5 e <NA>
    # 6:  6 f    B
    # 7:  7 g    B
    # 8:  8 h <NA>
    # 9:  9 i    C
    #10: 10 j <NA>
    

    或者另一个选项是fuzzyjoin

    library(fuzzyjoin)
    library(dplyr)
    fuzzy_left_join(df1, df2, by = c('id' = 'start', 'id' = 'end'), 
             match_fun = list(`>`, `<=`)) %>%
         select(id, c, cn = name)
    

    【讨论】:

    • df1$c 应该仍然完好无损。
    • merged 是预期的输出。无论如何,这似乎可以完成工作:mergedt &lt;- setDT(df1)[df2, cn := name, on = .(id &gt;= start, id &lt;= end)]。我只是更喜欢在tidyverse 中执行此操作,以最大程度地减少包加载。您介意详细说明发生了什么吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-26
    • 1970-01-01
    • 2018-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-14
    相关资源
    最近更新 更多