【问题标题】:wide to long data table transformation with variables in columns and rows具有列和行中的变量的宽到长数据表转换
【发布时间】:2017-08-07 20:17:34
【问题描述】:

我有一个包含多个表的 csv,其中的变量存储在行和列中。
关于这个 csv:

  1. 我想从“宽”到“长”
  2. 一个csv中有多个“数据框”
  3. 每个“数据框”都有不同类型的变量

> df3
     V1          V2    V3     V4      V5     V6      V7    V8
1   nyc 123 main st month      1       2      3       4     5
2   nyc 123 main st     x  58568  567567 567909   35876 56943
3   nyc 123 main st     y   5345    3673   3453    3467   788
4   nyc 123 main st     z  53223  563894 564456   32409 56155
5                                                            
6    la  63 main st month      1       2      3       4     5
7    la  63 main st     a  87035 7467456   3363     863 43673
8    la  63 main st     b    345     456    345     678   345
9    la  63 main st     c  86690 7467000   3018     185 43328
10                                                           
11   sf 953 main st month      1       2      3       4     5
12   sf 953 main st     x 457456    3455 345345   56457  3634
13   sf 953 main st     b   5345    3673   3453    3467   788
14   sf 953 main st     z 452111    -218 341892   52990  2846

> df4
18 city     address month      x       y      z       a     b       c
19  nyc 123 main st     1  58568    5345  53223    null  null    null
20  nyc 123 main st     2 567567    3673 563894    null  null    null
21  nyc 123 main st     3 567909    3453 564456    null  null    null
22  nyc 123 main st     4  35876    3467  32409    null  null    null
23  nyc 123 main st     5  56943     788  56155    null  null    null
24   la  63 main st     1   null    null   null   87035   345   86690
25   la  63 main st     2   null    null   null 7467456   456 7467000
26   la  63 main st     3   null    null   null    3363   345    3018
27   la  63 main st     4   null    null   null     863   678     185
28   la  63 main st     5   null    null   null   43673   345   43328
29   sf 953 main st     1 457456    null 452111    null  5345    null
30   sf 953 main st     2   3455    null   -218    null  3673    null
31   sf 953 main st     3 345345    null 341892    null  3453    null
32   sf 953 main st     4  56457    null  52990    null  3467    null
33   sf 953 main st     5   3634    null   2846    null   788    null

上面是我有的数据,下面是我想要的变换。

我最擅长使用 R,但我正在练习 Python,所以任何方法都有效。

【问题讨论】:

  • 可能是 this post 的副本,但我不明白一个 csv 中的多个“data.frames”是什么意思。我怀疑这意味着您将不得不使用多个 read.csv 语句。
  • 查看 tidyr 包中的 spread()。和 dplyr 包中的 bind_rows()。我认为他们应该实现你想要的。
  • 从问题中的打印数据重建df3 非常困难。对于未来,我建议在dput() 的输出中提供您的问题。这有助于其他人更快地回答您的问题并了解打印输出中看不到的内容结构(类型、类等)。

标签: python r dataframe data-manipulation data-munging


【解决方案1】:

OP 提供的样本数据集表明 csv 文件中的所有数据帧

  1. 具有相同的结构,即相同的列数、名称和位置
  2. 并且每月的列V4V8指的是所有“子框架”的相同月份1到5。

如果这是真的,那么我们可以将整个 csv 文件视为一个数据帧,并通过使用来自 data.table 包的 melt()dcast() 进行整形来将其转换为所需的格式:

library(data.table)
setDT(df3)[, melt(.SD, id.vars = paste0("V", 1:3), na.rm = TRUE)][
  V3 != "month", dcast(.SD, V1 + V2 + rleid(variable) ~ forcats::fct_inorder(V3))][
    , setnames(.SD, 1:3, c("city", "address", "month"))]
    city     address month      x    y      z       a    b       c
 1:   la  63 main st     1     NA   NA     NA   87035  345   86690
 2:   la  63 main st     2     NA   NA     NA 7467456  456 7467000
 3:   la  63 main st     3     NA   NA     NA    3363  345    3018
 4:   la  63 main st     4     NA   NA     NA     863  678     185
 5:   la  63 main st     5     NA   NA     NA   43673  345   43328
 6:  nyc 123 main st     1  58568 5345  53223      NA   NA      NA
 7:  nyc 123 main st     2 567567 3673 563894      NA   NA      NA
 8:  nyc 123 main st     3 567909 3453 564456      NA   NA      NA
 9:  nyc 123 main st     4  35876 3467  32409      NA   NA      NA
10:  nyc 123 main st     5  56943  788  56155      NA   NA      NA
11:   sf 953 main st     1 457456   NA 452111      NA 5345      NA
12:   sf 953 main st     2   3455   NA   -218      NA 3673      NA
13:   sf 953 main st     3 345345   NA 341892      NA 3453      NA
14:   sf 953 main st     4  56457   NA  52990      NA 3467      NA
15:   sf 953 main st     5   3634   NA   2846      NA  788      NA

Hadley 的 forcats 包中的 fct_inorder() 函数在这里用于按列的首次出现而不是按字母顺序 a、b、c、x、y、z 排序。

请注意,城市也是按字母顺序排列的。如果这很重要(但我怀疑它是),原始订单也可以通过使用来保留

forcats::fct_inorder(V1) + V2 + rleid(variable) ~ forcats::fct_inorder(V3)

dcast() 公式。

数据

不幸的是,OP 没有提供 dput(df3) 的结果,这使得重现问题中打印的数据集变得不必要地困难:

df3 <- readr::read_table(
  "     V1          V2    V3     V4      V5     V6      V7    V8
  1   nyc 123 main st month      1       2      3       4     5
  2   nyc 123 main st     x  58568  567567 567909   35876 56943
  3   nyc 123 main st     y   5345    3673   3453    3467   788
  4   nyc 123 main st     z  53223  563894 564456   32409 56155
  5                                                            
  6    la  63 main st month      1       2      3       4     5
  7    la  63 main st     a  87035 7467456   3363     863 43673
  8    la  63 main st     b    345     456    345     678   345
  9    la  63 main st     c  86690 7467000   3018     185 43328
  10                                                           
  11   sf 953 main st month      1       2      3       4     5
  12   sf 953 main st     x 457456    3455 345345   56457  3634
  13   sf 953 main st     b   5345    3673   3453    3467   788
  14   sf 953 main st     z 452111    -218 341892   52990  2846"
)
library(data.table)
setDT(df3)[, V2 := paste(X3, V2)][, c("X1", "X3") := NULL]
setDF(df3)[]
    V1          V2    V3     V4      V5     V6    V7    V8
1  nyc 123 main st month      1       2      3     4     5
2  nyc 123 main st     x  58568  567567 567909 35876 56943
3  nyc 123 main st     y   5345    3673   3453  3467   788
4  nyc 123 main st     z  53223  563894 564456 32409 56155
5              NA            NA      NA     NA    NA    NA
6   la  63 main st month      1       2      3     4     5
7   la  63 main st     a  87035 7467456   3363   863 43673
8   la  63 main st     b    345     456    345   678   345
9   la  63 main st     c  86690 7467000   3018   185 43328
10             NA            NA      NA     NA    NA    NA
11  sf 953 main st month      1       2      3     4     5
12  sf 953 main st     x 457456    3455 345345 56457  3634
13  sf 953 main st     b   5345    3673   3453  3467   788
14  sf 953 main st     z 452111    -218 341892 52990  2846

【讨论】:

    【解决方案2】:

    如果您的 df 有正确的列名,这将有所帮助,请在读取数据后插入列名。

    我已使用以下库,dplyrstringr 进行此分析,并且还重命名了前 3 列:

    df <- data.frame(stringsAsFactors=FALSE,
            city = c("nyc", "nyc", "nyc"),
         address = c("123 main st", "123 main st", "123 main st"),
           month = c("x", "y", "z"),
              X1 = c(58568L, 5345L, 53223L),
              X2 = c(567567L, 3673L, 563894L),
              X3 = c(567909L, 3453L, 564456L),
              X4 = c(35876L, 3467L, 32409L),
              X5 = c(56943L, 788L, 56155L)
    )
    
    df %>% gather(Type, Value, -c(city:month)) %>% 
            spread(month, Value) %>%
            mutate(month = str_sub(Type, 2, 2)) %>%
            select(-Type) %>%
            select(c(city, address, month, x:z))
    
    city     address month      x    y      z
    1  nyc 123 main st     1  58568 5345  53223
    2  nyc 123 main st     2 567567 3673 563894
    3  nyc 123 main st     3 567909 3453 564456
    4  nyc 123 main st     4  35876 3467  32409
    5  nyc 123 main st     5  56943  788  56155
    

    【讨论】:

    • OP 已要求重塑其 csv 文件中的多个表格。您的帖子仅展示了如何通过故意构建自己的简化数据集来重塑 一个 表。您将如何继续转换所有表以使您的帖子成为完整的答案?
    猜你喜欢
    • 2012-12-27
    • 1970-01-01
    • 1970-01-01
    • 2019-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-31
    • 1970-01-01
    相关资源
    最近更新 更多