【问题标题】:How do I split the value of a column based on a lookup table?如何根据查找表拆分列的值?
【发布时间】:2021-11-06 15:02:30
【问题描述】:

我有一个包含 id 和相关值的数据集:

df <- data.frame(id = c("1", "2", "3"), value = c("12", "20", "16"))

我有一个将id 与另一个参考标签ref 匹配的查找表:

lookup <- data.frame(id = c("1", "1", "1", "2", "2", "3", "3", "3", "3"), ref = c("a", "b", "c", "a", "d", "d", "e", "f", "a"))

注意idref是多对多匹配:同一个id可以关联多个ref,同一个ref可以关联多个id

我正在尝试将与df$id 列关联的value 平均拆分为关联的ref 列。输出数据集如下所示:

output <- data.frame(ref = "a", "b", "c", "d", "e", f", value = "18", "4", "4", "14", "4", "4")
ref value
a 18
b 4
c 4
d 14
e 4
f 4

我尝试将其分为四个步骤:

  1. lookup 上调用pivot_wider,将具有相同id 值的行转换为列(例如,abc。)
  2. 基于id合并两个数据集
  3. 将每个df$value平分成abc等不为空的列
  4. 转置数据集并对id 列求和。

不过,我不知道如何使步骤 (3) 起作用,我怀疑有一种更简单的方法。

【问题讨论】:

    标签: r dataframe pivot reshape


    【解决方案1】:

    这是一个潜在的逻辑。将valuedf 合并到lookup by id,将value 除以匹配行数,然后按ref 分组并求和。然后选择你想要的方式。

    基础R

    tmp <- merge(lookup, df, by="id", all.x=TRUE)
    tmp$value <- ave(as.numeric(tmp$value), tmp$id, FUN=\(x) x/length(x) )
    aggregate(value ~ ref, tmp, sum)
    

    dplyr

    library(dplyr)
    lookup %>%
      left_join(df, by="id") %>%
      group_by(id) %>% 
      mutate(value = as.numeric(value) / n() ) %>%
      group_by(ref) %>%
      summarise(value = sum(value))
    

    数据表

    library(data.table)
    setDT(df)
    setDT(lookup)
    lookup[df, on="id", value := as.numeric(value)/.N, by=.EACHI][
       , .(value = sum(value)), by=ref]
    
    #   ref value
    #1:   a    18
    #2:   b     4
    #3:   c     4
    #4:   d    14
    #5:   e     4
    #6:   f     4
    

    【讨论】:

      【解决方案2】:

      这可能有效

      lookup %>%
        left_join(lookup %>%
                    group_by(id) %>%
                    summarise(n = n()) %>%
                    left_join(dummy, by = "id") %>%
                    mutate(value = as.numeric(value)) %>%
                    mutate(repl = value/n) %>%
                    select(id, repl) ,
                  by = "id"
        ) %>% select(ref, repl) %>%
        group_by(ref) %>% summarise(value = sum(repl))
      
        ref   value
        <chr> <dbl>
      1 a        18
      2 b         4
      3 c         4
      4 d        14
      5 e         4
      6 f         4
      

      【讨论】:

        【解决方案3】:

        @thelatemail 的 answer 的变体,带有基本管道。

        merge(df, lookup) |> type.convert(as.is=TRUE) |>
          transform(value=ave(value, id, FUN=\(x) x/length(x))) |>
          with(aggregate(list(value=value), list(ref=ref), sum))
        #   ref value
        # 1   a    18
        # 2   b     4
        # 3   c     4
        # 4   d    14
        # 5   e     4
        # 6   f     4
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-08-28
          • 2021-11-11
          • 1970-01-01
          • 2022-01-05
          • 2021-01-17
          相关资源
          最近更新 更多