【问题标题】:Using pivot_longer to separate columns into long format使用 pivot_longer 将列分隔为长格式
【发布时间】:2021-02-09 16:45:20
【问题描述】:

我有一个非有限长度的 df,如下表所示。 这里的示例只有 2 个特征:“脂质”和“密度”。其他行可能有 50 个或更多特征。但将始终具有相同的特征、单位、方法模式。使用 read_excel 导入 R 时,它会将非唯一名称更改为 xxx...[col.number]。我想使用 pivot_longer 将数据从宽转换为长格式。我在操作该函数时遇到了困难,希望能得到一些帮助。我想要的最终列名是 geno_name、observation_id、trait、value、unit、method

样本数据

所需的输出(不带 drop_na 语句来显示示例)

x <- structure(list(geno_name = "MB mixed", observation_id = 10, lipids = NA, 
    unit...3 = NA, method...4 = NA, density = 1.125, unit...6 = "g cm^-3", 
    method...7 = "3D scanning"), class = "data.frame", row.names = c(NA,-1L))

到目前为止我有:

x %>% pivot_longer(
    cols = 3:ncol(x),
    names_to = c("trait","unit","method"),
    #need help with these other arguments
    values_drop_na = T)

【问题讨论】:

    标签: r


    【解决方案1】:

    要以“长”格式使用的数据列名称在列名称中的模式并不相同。因此,包含的步骤是

    • 通过添加带有paste/str_c 的列来重命名列名中没有..._ 的列

    • 使用pivot_longer 重塑为长格式 - 考虑到名称中带有names_sepnames_pattern 的模式,将names_to 指定为c(".value", "trait") 的向量,其顺序与我们想要列值的顺序相同以及要存储为单独列的后缀值

    • 一旦我们重构,根据“特征”中的值创建一个分组列(其中一些是数字 - 创建一个逻辑向量并获得累积和)以及其他分组“geno_name”、“observation_id”(但它不会创建一个唯一的列))

    • 现在summarise 其他列通过在基于 NA 元素排序后切片第一行,即如果没有 NA,第一个值将是非 NA,否则它将是 NA

    library(dplyr)
    library(stringr)
    library(tidyr)
    x %>%
       rename_at(vars(names(.)[!str_detect(names(.), "[_.]+")]), 
           ~ str_c("value...", .)) %>%
       pivot_longer(cols = 3:ncol(.), 
          names_to = c(".value", "trait"), names_sep = "\\.+") %>% 
       group_by(geno_name, observation_id, 
           grp = cumsum(str_detect(trait, "\\D+"))) %>%
       summarise(across(everything(), ~ .[order(is.na(.))][1]),
             .groups = 'drop') %>%
       select(-grp)
    

    -输出

    # A tibble: 2 x 6
    #  geno_name observation_id trait   value unit    method     
    #  <chr>              <dbl> <chr>   <dbl> <chr>   <chr>      
    #1 MB mixed              10 lipids  NA    <NA>    <NA>       
    #2 MB mixed              10 density  1.12 g cm^-3 3D scanning
    

    数据

    x <- structure(list(geno_name = "MB mixed", observation_id = 10, lipids = NA, 
        unit...3 = NA, method...4 = NA, density = 1.125, unit...6 = "g cm^-3", 
        method...7 = "3D scanning"), class = "data.frame", row.names = c(NA, 
    -1L))
    

    【讨论】:

    • 谢谢,但不是我想要的。寻找具有以下列名称的输出:geno_name、observation_id、trait、value、unit、method。将“密度”和“脂质”放入特征中,将这些列的值放入值中,并且对于相应的单元和方法具有相同的想法
    • 看起来更好,但仍然不完全。 1)如果你看你的输出,它的脂质单位是错误的,密度单位没有价值。 2) 如果表中有多个性状,而不仅仅是脂质和密度怎么办?我不知道每个特征的名称,所以我可以使用正则表达式来识别特征名称,因为它将是所有没有“\\.{3}”的列名
    • @Patrick 我用您预期的输出检查了更新。现在好像匹配了
    • 太棒了!在末尾添加了 %>% drop_na() 以删除具有 na 并因此具有空值的行。通过添加其他特征、单位和方法对其他数据进行测试,效果非常好。非常感谢!接受为解决方案。
    • @Patrick 您是否可以发布一个新问题,以便更容易理解您提到的问题
    猜你喜欢
    • 1970-01-01
    • 2020-08-28
    • 1970-01-01
    • 1970-01-01
    • 2020-08-07
    • 1970-01-01
    • 2022-11-15
    • 1970-01-01
    • 2021-01-19
    相关资源
    最近更新 更多