具有多个键和值的从长到宽的数据框

时间:2018-11-26 16:16:12

标签: r tidyr data-manipulation

我有一个很长很整齐的数据框,我必须扩大它。现在通常我用tidyr::spread()函数解决这个问题。但是现在我必须处理多个键,值和命名约定。

我的示例数据框如下所示:

library(tidyverse)

df <- structure(list(Jaar = c(2014, 2014, 2015, 2015), Gemeente = c("Aa en Hunze", 
"Aa en Hunze", "Aa en Hunze", "Aa en Hunze"), aantal_inw = c(25286L, 
25286L, 25286L, 25286L), Categorie = c("Bedrijven", "Evenementen", 
"Bedrijven", "Evenementen"), incidenten = c(6, 13, 2, 8), per_1000inw = c(0.2, 
0.5, 0.1, 0.3)), class = c("tbl_df", "tbl", "data.frame"), .Names = c("Jaar", 
"Gemeente", "aantal_inw", "Categorie", "incidenten", "per_1000inw"
), row.names = c(NA, -4L))


# A tibble: 4 x 6
   Jaar Gemeente    aantal_inw Categorie   incidenten per_1000inw
  <dbl> <chr>            <int> <chr>            <dbl>       <dbl>
1  2014 Aa en Hunze      25286 Bedrijven            6         0.2
2  2014 Aa en Hunze      25286 Evenementen         13         0.5
3  2015 Aa en Hunze      25286 Bedrijven            2         0.1
4  2015 Aa en Hunze      25286 Evenementen          8         0.3

我希望将所有这些数据都放在一行中,其中Gemeente(市政性)是观察值。

所需的结果(看起来可能很不整洁)如下所示:

tibble::tribble(
      ~Gemeente, ~aantal_inw, ~Bedrijven_2014_incidenten, ~Bedrijven_2015_incidenten, ~Evenementen_2014_incidenten, ~Evenementen_2015_incidenten, ~Bedrijven_2014_per_1000inw, ~Bedrijven_2015_per_1000inw, ~Evenementen_2014_per_1000inw, ~Evenementen_2015_per_1000inw,
  "Aa en Hunze",      25286L,                         6L,                         2L,                          13L,                           8L,                         0.2,                         0.1,                           0.5,                           0.3
  )

# A tibble: 1 x 10
  Gemeente    aantal_inw Bedrijven_2014_i… Bedrijven_2015_i… Evenementen_2014… Evenementen_201… Bedrijven_2014_… Bedrijven_2015_… Evenementen_201… Evenementen_201…
  <chr>            <int>             <int>             <int>             <int>            <int>            <dbl>            <dbl>            <dbl>            <dbl>
1 Aa en Hunze      25286                 6                 2                13                8              0.2              0.1              0.5              0.3

非常感谢所有帮助。

3 个答案:

答案 0 :(得分:3)

library(tidyverse)

df %>%
  gather(v1, v2, -Jaar, -Gemeente, -aantal_inw, -Categorie) %>%
  unite(v3, Categorie, Jaar, v1) %>%
  spread(v3, v2) %>%
  data.frame()

#      Gemeente aantal_inw Bedrijven_2014_incidenten Bedrijven_2014_per_1000inw Bedrijven_2015_incidenten Bedrijven_2015_per_1000inw
# 1 Aa en Hunze      25286                         6                        0.2                         2                        0.1
#   Evenementen_2014_incidenten Evenementen_2014_per_1000inw Evenementen_2015_incidenten Evenementen_2015_per_1000inw
# 1                          13                          0.5                           8                          0.3

请注意,我最终仅将data.frame()用于可视化目的(即,打印整个列的名称以供您检查是否可以)

答案 1 :(得分:1)

untidy_df <- df %>% 
  gather(metric, value, 5:6) %>% 
  unite(combined_categories, c(Categorie, Jaar, metric)) %>% 
  spread(combined_categories, value)

答案 2 :(得分:0)

或使用data.table

library(data.table)
dt <- dcast(as.data.table(df), ... ~ Categorie + Jaar, 
            value.var=c("incidenten", "per_1000inw"))

给予

> dt
      Gemeente aantal_inw incidenten_Bedrijven_2014 incidenten_Bedrijven_2015
1: Aa en Hunze      25286                         6                         2
   incidenten_Evenementen_2014 incidenten_Evenementen_2015
1:                          13                           8
   per_1000inw_Bedrijven_2014 per_1000inw_Bedrijven_2015
1:                        0.2                        0.1
   per_1000inw_Evenementen_2014 per_1000inw_Evenementen_2015
1:                          0.5                          0.3

注意:在使用df <- as.data.frame(dt)之后再次获得data.frame