【问题标题】:R multiply unequal dataframes based on specific column valuesR根据特定列值乘以不相等的数据帧
【发布时间】:2020-02-27 23:15:03
【问题描述】:

更新问题以包含从 df1 传递到输出的额外列,并添加主 df 有 700 万行。


我有两个数据框,类似于Pandas SO Question

我需要在名称匹配的地方将它们相乘。我不确定如何干净地完成这项工作。有没有一个apply函数可以轻松做到这一点?

DF1:(有 16 列额外数据,700 万行长)

Data1   Data2   Name      Value
aa      bb      sample1   50
ff      ff      sample1   100
ef      fd      sample1   75
ff      df      sample2   100
bbf     ad3     sample2   200
dd      a       sample2   300
33      3rf     sample3   25
ddd     dd      sample3   50
dd      dd      sample3   40

DF2:

Name      Value
sample1   1
sample2   0.5
sample3   2

输出:(带有未显示的额外 16 列)

Data1   Data2   Name      Value
aa      bb      sample1   50
ff      ff      sample1   100
ef      fd      sample1   75
ff      df      sample2   50
bbf     ad3     sample2   100
dd      a       sample2   150
33      3rf     sample3   50
ddd     dd      sample3   100
dd      dd      sample3   80

【问题讨论】:

    标签: r lapply sapply mapply


    【解决方案1】:

    我们可以使用left_joininner_join 连接两个数据框,然后将相应的Value 列相乘。使用dplyr 可以这样做:

    library(dplyr)
    
    inner_join(df1, df2, by = 'Name') %>%
       mutate(Value = Value.x * Value.y) %>%
       select(names(df1))
    
    #     Name Value
    #1 sample1    50
    #2 sample1   100
    #3 sample1    75
    #4 sample2    50
    #5 sample2   100
    #6 sample2   150
    #7 sample3    50
    #8 sample3   100
    #9 sample3    80
    

    数据

    df1 <- structure(list(Name = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 
    3L, 3L), .Label = c("sample1", "sample2", "sample3"), class = "factor"), 
    Value = c(50L, 100L, 75L, 100L, 200L, 300L, 25L, 50L, 40L
    )), class = "data.frame", row.names = c(NA, -9L))
    
    df2 <- structure(list(Name = structure(1:3, .Label = c("sample1", "sample2", 
    "sample3"), class = "factor"), Value = c(1, 0.5, 2)), class = "data.frame", 
    row.names = c(NA, -3L))
    

    【讨论】:

    • 我已更新问题以包括数据框的大小和需要通过的额外列。我将尝试实现这些答案中的每一个,但我认为这些信息可能是相关的。
    • @Steve 我认为我的答案不会因其他列而发生任何变化。
    【解决方案2】:

    最直接的方法是使用match 以正确的顺序获取df2 的行索引。

    df2$Value[match(df1$Name, df2$Name)] * df1$Value
    

    您还可以将df2 转换为名称基于Name 列的向量。然后使用df1Name 列从中提取值。

    df1$Value * setNames(df2$Value, df2$Name)[df1$Name]
    

    【讨论】:

    • 我已更新问题以包括数据框的大小和需要通过的额外列。我将尝试实现这些答案中的每一个,但我认为这些信息可能是相关的。
    【解决方案3】:

    你可以使用data.table包:

    library(data.table)
    setDT(df1)[setDT(df2), Value_new := Value * i.Value, on = "Name"]
    
    #     Data1  Data2    Name Value Value_new
    # 1:     aa     bb sample1    50        50
    # 2:     ff     ff sample1   100       100
    # 3:     ef     fd sample1    75        75
    # 4:     ff     df sample2   100        50
    # 5:    bbf    ad3 sample2   200       100
    # 6:     dd      a sample2   300       150
    # 7:     33    3rf sample3    25        50
    # 8:    ddd     dd sample3    50       100
    # 9:     dd     dd sample3    40        80
    

    【讨论】:

    • 我已更新问题以包括数据框的大小和需要通过的额外列。我将尝试实现这些答案中的每一个,但我认为这些信息可能是相关的。
    【解决方案4】:

    您可以尝试下面的基本 R 代码,使用 merge

    DF1$Value <- do.call(`*`,merge(DF1[c("Name","Value")],DF2,all = TRUE,by="Name")[-1])
    

    这样

    > DF1
      Data1 Data2    Name Value
    1    aa    bb sample1    50
    2    ff    ff sample1   100
    3    ef    fd sample1    75
    4    ff    df sample2    50
    5   bbf   ad3 sample2   100
    6    dd     a sample2   150
    7    33   3rf sample3    50
    8   ddd    dd sample3   100
    9    dd    dd sample3    80
    

    数据

    DF1 <- structure(list(Data1 = c("aa", "ff", "ef", "ff", "bbf", "dd", 
    "33", "ddd", "dd"), Data2 = c("bb", "ff", "fd", "df", "ad3", 
    "a", "3rf", "dd", "dd"), Name = c("sample1", "sample1", "sample1", 
    "sample2", "sample2", "sample2", "sample3", "sample3", "sample3"
    ), Value = c(50L, 100L, 75L, 100L, 200L, 300L, 25L, 50L, 40L)), class = "data.frame", row.names = c(NA, 
    -9L))
    
    DF2 <- structure(list(Name = c("sample1", "sample2", "sample3"), Value = c(1, 
    0.5, 2)), class = "data.frame", row.names = c(NA, -3L))
    

    【讨论】:

    • 我已更新问题以包括数据框的大小和需要通过的额外列。我将尝试实现这些答案中的每一个,但我认为这些信息可能是相关的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-14
    • 2018-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多