【问题标题】:Turn specific row values into columns using R使用 R 将特定的行值转换为列
【发布时间】:2021-10-22 08:56:58
【问题描述】:

我有一个类似于下面列出的数据集

v1 <-c('name1','0/0','0/1','1/1','name2','0/0','1/1','name3','0/0','0/1','1/1','name4','0/0','0/1','1/1','name5','0/0','1/1')
v2 <- c(NA,95,3,2,NA,98,2,NA,93,5,2,NA,94,3,3,NA,96,4)
df <- cbind(v1,v2)
df <- as.data.frame(df)
df

看起来像:

v1 v2
name1 NA
0/0 95
0/1 3
1/1 2
name2 NA
0/0 98
1/1 2
name3 NA
0/0 93
0/1 5
1/1 2

如何将数据框重塑为:

names 0/0 0/1 1/1
name1 95 3 2
name2 98 NA 2
name3 93 5 2

使用重塑我得到的最接近的是:

v1 0/0 0/1 1/1
1 95 . .
2 . 3 .
3 . . 2
4 98 . .
5 . . 2

谢谢!

【问题讨论】:

    标签: r data-manipulation reshape2 melt


    【解决方案1】:

    它是如何工作的:

    1. 创建一个id_Group
    2. group_splitid_Group
    3. 现在你有一个数据框列表my_list
    4. 使用lapplypivot_wider 列表中的所有数据框
    5. 使用bind_rows 将数据帧列表合并为一个数据帧
    6. 要获得name 列,请使用pivot_longer 并进行一些后续调整:
    library(tidyverse)
    
    my_list <- df %>% 
        mutate(id_Group = cumsum(is.na(v2))) %>% 
        group_split(id_Group) 
    
    df_list <- lapply(1:length(my_list), 
                      function(x) (pivot_wider(my_list[[x]], names_from = v1, values_from = v2)))
    
    bind_rows(df_list) %>% 
        pivot_longer(
            cols = starts_with("name"),
            names_to = "name"
        ) %>% 
        group_by(id_Group) %>% 
        filter(row_number()==1) %>% 
        ungroup() %>% 
        select(name, contains("/"), -id_Group, -value)
    
    
      name  `0/0` `0/1` `1/1`
      <chr> <chr> <chr> <chr>
    1 name1 95    3     2    
    2 name1 98    NA    2    
    3 name1 93    5     2    
    4 name1 94    3     3    
    5 name1 96    NA    4    
    

    【讨论】:

      【解决方案2】:

      如果你愿意使用tidyverse 组包而不是reshape2,你可以试试这个。步骤是

      1. 创建一个新的名称列并用v1 中包含字符串“names”的任何值填充它
      2. fill 新的names 列,filterv2 列中包含NA 的所有行
      3. 使用tidyr::pivot_wider 更改为宽格式数据帧
      v1 <-c('name1','0/0','0/1','1/1','name2','0/0','1/1','name3','0/0','0/1','1/1','name4','0/0','0/1','1/1','name5','0/0','1/1')
      v2 <- c(NA,95,3,2,NA,98,2,NA,93,5,2,NA,94,3,3,NA,96,4)
      df <- cbind(v1,v2)
      df <- as.data.frame(df)
      
      library(tidyverse)
      
      df %>%
        mutate(names = ifelse(str_detect(v1, 'name'), v1, NA)) %>%
        fill(names) %>%
        filter(!is.na(v2)) %>%
        pivot_wider(names_from = v1,
                    values_from = v2)
      #> # A tibble: 5 x 4
      #>   names `0/0` `0/1` `1/1`
      #>   <chr> <chr> <chr> <chr>
      #> 1 name1 95    3     2    
      #> 2 name2 98    <NA>  2    
      #> 3 name3 93    5     2    
      #> 4 name4 94    3     3    
      #> 5 name5 96    <NA>  4
      

      reprex package (v2.0.0) 于 2021-08-20 创建

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多