【问题标题】:reshape from long to wide of non-categorical values从长到宽的非分类值重塑
【发布时间】:2020-03-21 08:20:58
【问题描述】:

我需要将具有非分类值的日期从长调整为宽 而不是相同数量的值。

数据框示例:

df_long <- as.data.frame(cbind(c("id A",  "b",    "b",    "d",    "d","id B", "kh",   "kk",   "ip", "id C", "99", "id D", "id E"),c(1,1,1,1,1, 2,2,2,2,3,3,1,1)))

我需要这个:

df_wide <- as.data.frame(rbind(c("id A", "b", "b", "d", "d"), c("id B", "kh", "kk", "ip", ""), c("id C", "99", "", "", ""), c("id D", "", "", "", ""), c("id E", "", "", "", "")))

我不知道如何重塑它,因为值不是分类的,而且不是每个 id 都有相同数量的值。

所以我想知道如何将此类数据从长到宽以及从宽到长重塑。

感谢您的帮助!

【问题讨论】:

    标签: r reshape2 data-transform


    【解决方案1】:

    你可以这样做:

    a = aggregate(V1~V2,transform(df_long,V2 = cumsum(grepl("id",V1))),paste,collapse=',')[,2]
    read.csv(text=a,header = FALSE,fill = TRUE)
        V1 V2 V3 V4 V5
    1 id A  b  b  d  d
    2 id B kh kk ip   
    3 id C 99         
    4 id D            
    5 id E   
    

    既然你需要把它转换回来,那么你应该这样做:

     f<-read.csv(text = with(df_long,tapply(V1,cumsum(grepl("id",V1)),paste0,collapse=",")), 
                  header = FALSE, fill = TRUE,stringsAsFactors = F,na.strings = "")
    
    
     print(f,na = "")
        V1 V2 V3 V4 V5
    1 id A  b  b  d  d
    2 id B kh kk ip   
    3 id C 99         
    4 id D            
    5 id E
    

    现在要将其转换回您的 long_data,您可以这样做:

    with(g <- transform(stack(f),ind = c(row(f))),na.omit(g[order(ind),]))
       values ind
    1    id A   1
    6       b   1
    11      b   1
    16      d   1
    21      d   1
    2    id B   2
    7      kh   2
    12     kk   2
    17     ip   2
    3    id C   3
    8      99   3
    4    id D   4
    5    id E   5
    

    【讨论】:

    • 非常感谢!我可以询问如何将其转换回来的建议吗?
    • @Briis300 你想如何将其转换回来?喜欢如何从这些数据中获取 V2?
    • V2数据只是每个创建的id的运行id号(datatable:cumsum)
    【解决方案2】:

    tidyverse 选项

    library(tidyverse)
    df_long %>%
        separate(V1, into = c("id", "val"), fill = "left") %>%
        select(-V2) %>%
        mutate(row = cumsum(!is.na(id))) %>%
        fill(id) %>%
        group_by(row) %>%
        mutate(col = 1:n()) %>%
        ungroup() %>% 
        pivot_wider(
            id_cols = c(row, id), 
            names_from = col, 
            names_prefix = "V",
            values_from = val,
            values_fill = list(val = ""))
    ## A tibble: 5 x 7
    #    row id    V1    V2    V3    V4    V5
    #  <int> <chr> <chr> <chr> <chr> <chr> <chr>
    #1     1 id    A     b     b     d     d
    #2     2 id    B     kh    kk    ip    ""
    #3     3 id    C     99    ""    ""    ""
    #4     4 id    D     ""    ""    ""    ""
    #5     5 id    E     ""    ""    ""    ""
    

    PS。似乎df_long$V2 列中的条目未在df_wide 中使用。对吗?

    【讨论】:

    • 是的,df_long$V2 只是用作 id。您的解决方案似乎很顺利,尽管它会吐出一条错误消息,指出它找不到 pivot_wider。也许是一个过时的包?
    • @Briis300 pivot_wider is the "new" spread(将被弃用)来自tidyr;如果你更新到 tidyr_1.0.0 它应该可以工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-25
    • 2014-06-29
    • 2019-11-22
    相关资源
    最近更新 更多