【问题标题】:List of data frames containing row and column indices to select data from a larger data frame包含行和列索引的数据框列表,用于从更大的数据框中选择数据
【发布时间】:2018-05-11 21:32:19
【问题描述】:

我有一个数据框列表。其中一列包含数据框的名称:

a <- data.frame(PIN = c(1:3), Item = c("a", "a", "a"))
b <- data.frame(PIN = c(4:6), Item = c("b", "b", "b"))
List <- list(a, b)

还有一个更大的数据框,我想从中提取数据。我的数据框列表中第一列中的值对应于第一列或更大数据框中的值,我的数据框列表第二列中的名称/值对应于更大数据框中的列名:

DF <-data.frame(PIN = c(1:10), a = c(101:110), b = c(201:210), c = c(301:310))

我想将列添加到从 DF 提取数据的列表中的数据框中,使用 PIN 作为行索引,使用 Item 作为列索引。所以基本上,我最终会得到:

a <- data.frame(PIN = c(1:3), Item = c("a", "a", "a"), a = c(101:103))
b <- data.frame(PIN = c(4:6), Item = c("b", "b", "b"), b = c(204:206))
List <- list(a, b)

我该怎么做?

【问题讨论】:

    标签: r


    【解决方案1】:

    有了tidyrdplyrpurrr,我们可以这样做:

    DF <- tidyr::gather(DF, key = "Item", value, -PIN)
    
    purrr::map(List, dplyr::left_join, DF, by = c("PIN", "Item"))
    
    [[1]]
      PIN Item value
    1   1    a   101
    2   2    a   102
    3   3    a   103
    
    [[2]]
      PIN Item value
    1   4    b   204
    2   5    b   205
    3   6    b   206
    

    请注意,您将收到一条警告消息,因为示例数据包含因子。在构造数据框时添加stringsAsFactors = FALSE,以避免出现此警告消息。

    您可以使用基本 R 的 lapply 替换 purrr map 函数:

    lapply(List, dplyr::left_join, DF, by = c("PIN", "Item"))
    

    此外,Uwe 解决方案的一种替代方案可能是:

    library(tidyverse)
    
    DF <- gather(DF, key = "Item", value, -PIN)
    
    List %>% 
      map(mutate_if, is.factor, as.character) %>% # optional, but solves the warning message by converting factors to character
      map_df(rbind, .id = "id") %>% 
      left_join(DF) %>% 
      split(.$id)
    
    $`1`
      id PIN Item value
    1  1   1    a   101
    2  1   2    a   102
    3  1   3    a   103
    
    $`2`
      id PIN Item value
    4  2   4    b   204
    5  2   5    b   205
    6  2   6    b   206
    

    数据:

    # Create list
    List <- list(
      data.frame(PIN = c(1:3), Item = c("a", "a", "a")),
      data.frame(PIN = c(4:6), Item = c("b", "b", "b"))
    )
    
    # Create data frame
    DF <- data.frame(
      PIN = c(1:10), 
      a = c(101:110), 
      b = c(201:210), 
      c = c(301:310)
    )
    

    【讨论】:

    • Np,很乐意为您提供帮助
    【解决方案2】:

    您可能需要重新考虑您的数据结构:

    1. 结构相同的 data.frame 列表可以组合成一个更大的数据对象,从而避免遍历列表元素。
    2. 由于DF 的“有效负载”列abc 都包含相同的数据类型,所以DF 可以从宽格式重新调整为长格式。这会将列名转换为可以更轻松地用于查找操作的数据元素。

    所以,我的建议是:

    library(data.table)
    
    keys <- rbindlist(List, idcol = TRUE)
    DT <- setDT(melt(DF, id.vars = "PIN", variable.name = "Item"))
    DT[keys, on = .(PIN, Item)]
    
       PIN Item value .id
    1:   1    a   101   1
    2:   2    a   102   1
    3:   3    a   103   1
    4:   4    b   204   2
    5:   5    b   205   2
    6:   6    b   206   2
    

    如果还需要列表结果:

    split(DT[keys, on = .(PIN, Item)], by = ".id")
    
    $`1`
       PIN Item value .id
    1:   1    a   101   1
    2:   2    a   102   1
    3:   3    a   103   1
    
    $`2`
       PIN Item value .id
    1:   4    b   204   2
    2:   5    b   205   2
    3:   6    b   206   2
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-27
      • 1970-01-01
      • 2016-02-14
      • 2021-10-03
      • 1970-01-01
      • 2019-03-04
      • 1970-01-01
      • 2020-07-12
      相关资源
      最近更新 更多