【问题标题】:Convert long form data frame with multiple variables to wide format tidy data [duplicate]将具有多个变量的长格式数据框转换为宽格式整洁数据[重复]
【发布时间】:2020-11-28 14:25:09
【问题描述】:

想检查我们是否可以投射多个列。比如如下图

数据:

structure(list(Date = c("03-01-2016", "04-01-2016", "05-01-2016", 
"06-01-2016", "07-01-2016", "09-01-2016"), Cat = c("A", "A", 
"B", "D", "D", "D"), Sales = c(39L, 28L, 50L, 40L, 39L, 41L), 
    products = c(3L, 6L, 4L, 2L, 1L, 5L)), class = "data.frame", row.names = c(NA, 
-6L))
Date       Cat  Sales   products
03-01-2016  A   39        3
04-01-2016  A   28        6
05-01-2016  B   50        4
06-01-2016  D   40        2
07-01-2016  D   39        1
09-01-2016  D   41        5

预期输出

Date        Sales _A    Sales _B    Sales _C    Products _A Products _B Products _C
03-01-2016    39           0          0              3          0          0
04-01-2016    28           0          0              6          0          0
05-01-2016     0          50           0             0          4           0
06-01-2016     0          0           40             0          0           2
07-01-2016     0          0           39             0          0           1 
09-01-2016     0          0           41             0          0           5

【问题讨论】:

    标签: r tidyr


    【解决方案1】:

    这可以通过pivot_wider() 1.0.0 版或更新版本的tidyr 包中的函数来完成。

    首先,我们将products 列重命名为Products。然后我们使用pivot_wider() 参数从输入数据框的Cat 列中分配列名,从ProductsSales 列中分配列名,使用names_glue{.value}_{Cat} 设置为列名,并且用 0 填充缺失值。

    textData <- "Date       Cat  Sales   products
    03-01-2016  A   39        3
    04-01-2016  A   28        6
    05-01-2016  B   50        4
    06-01-2016  D   40        2
    07-01-2016  D   39        1
    09-01-2016  D   41        5"
    
    data <- read.table(text = textData,header=TRUE)
    library(tidyr)
    
    data %>% rename(Products = products) %>% 
         pivot_wider(.,Date,names_from=Cat,
                         values_from=c(Sales,Products),
                         names_glue="{.value}_{Cat}",
                         values_fill=0)
    

    ...和输出:

    # A tibble: 6 x 7
      Date       Sales_A Sales_B Sales_D Products_A Products_B Products_D
      <chr>        <int>   <int>   <int>      <int>      <int>      <int>
    1 03-01-2016      39       0       0          3          0          0
    2 04-01-2016      28       0       0          6          0          0
    3 05-01-2016       0      50       0          0          4          0
    4 06-01-2016       0       0      40          0          0          2
    5 07-01-2016       0       0      39          0          0          1
    6 09-01-2016       0       0      41          0          0          5
    >
    

    解释names_glue

    tidyverse 使用 glue 包来解释字符串文字,评估并将它们插入到 R 函数的参数字符串中。 tidyr 将粘连与 pivot specification 结合起来,以确定在将数据框从窄格式旋转到宽格式时如何准确命名列,反之亦然。

    根据tidyr 文档,names_glue="{.value}_{Cat}" 被解释为生成规范数据框,该数据框控制输出数据框中列的命名方式。

    pivot 规范是一个数据框,宽格式版本中的每一列对应长格式中不存在的数据,以及两个以 . 开头的特殊列:.name列的名称,.value 提供单元格中的值将进入的列的名称。

    对于此问题中的pivot_wider() 调用,数据透视规范数据框如下所示。

    # A tibble: 6 x 3
      .name      .value   Cat  
      <chr>      <chr>    <chr>
    1 Sales_A    Sales    A    
    2 Sales_B    Sales    B    
    3 Sales_D    Sales    D    
    4 Products_A Products A    
    5 Products_B Products B    
    6 Products_D Products D    
    > 
    

    注意: 在输出数据框中,我没有在列名中包含空格,如问题所示,因为它们在 R 中使用起来很麻烦。另请注意,问题有一个 @ 987654345@当原始数据没有C类时输出列。相反,它有一个 D 类别。

    另请注意:tidyr 1.0.0 于 2019 年 10 月推出。tidyr::pivot_wider() 取代了 tidyr::spread() 函数,该函数已在 1.0.0 版中弃用。

    【讨论】:

    • 我尝试了您的解决方案,但不确定为什么它不起作用;在我的数据框中不起作用,但您使用的那个完全正常。我使用了@ThomasIsCoding 解决方案,效果很好..
    • @krushnachChandra - 您是否收到错误消息?如果是这样,错误是什么?如果没有,发生了什么?如果您需要帮助调试代码,请发布一个新问题,其中包含 minimal, reproducible example,以及代码生成的任何错误消息。
    • "please post a new question" 我希望我可以,但我被阻止在这个 R 部分提出问题,但我会在其他部分发布我的问题并在此处分享链接
    【解决方案2】:

    这是使用 reshape 的基本 R 选项

    reshape(df,direction = "wide",idvar = "Date",timevar = "Cat")
    

    给了

    > reshape(df,direction = "wide",idvar = "Date",timevar = "Cat")
            Date Sales.A products.A Sales.B products.B Sales.D products.D
    1 03-01-2016      39          3      NA         NA      NA         NA
    2 04-01-2016      28          6      NA         NA      NA         NA
    3 05-01-2016      NA         NA      50          4      NA         NA
    4 06-01-2016      NA         NA      NA         NA      40          2
    5 07-01-2016      NA         NA      NA         NA      39          1
    6 09-01-2016      NA         NA      NA         NA      41          5
    

    数据

    df <- structure(list(Date = c("03-01-2016", "04-01-2016", "05-01-2016", 
    "06-01-2016", "07-01-2016", "09-01-2016"), Cat = c("A", "A", 
    "B", "D", "D", "D"), Sales = c(39L, 28L, 50L, 40L, 39L, 41L), 
        products = c(3L, 6L, 4L, 2L, 1L, 5L)), class = "data.frame", row.names = c(NA, 
    -6L))
    

    【讨论】:

    • 谢谢。但是我们不能在这里看到“猫”的名字吗?
    • Cat 中的值作为预期输出列名的后缀
    猜你喜欢
    • 2017-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    相关资源
    最近更新 更多