Tidyr:将数据分布在多个数据帧中

时间:2018-11-25 20:35:58

标签: r tidyr

我在R中具有以下数据框:

Date | ID | Shape | Size | Color
---- | -- | ----- | ---- | ----
1/1/1| 01 | RND   | L    | RED
1/1/1| 02 | RND   | M    | BRN
1/1/1| 03 | SQR   | S    | BLK 
1/2/1| 01 | TRI   | S    | GRN
1/2/1| 02 | SQR   | L    | BLK
1/2/1| 03 | RND   | L    | BLU 
1/3/1| 01 | OVL   | M    | YEL
1/3/1| 02 | STR   | L    | ORA
1/3/1| 03 | CUB   | S    | PUR
...  | .. | ...   | ...  | ...

我想将此数据帧转换为以下单独的数据帧:

df_shape:

Date | Shape.id1 | Shape.id2 | Shape.id3
---- | --------- | --------- | ---------
1/1/1| RND       | RND       | SQR
1/2/1| TRI       | SQR       | RND
1/3/1| OVL       | STR       | CUB
...  | ...       | ...       | ...


df_size:

Date | Size.id1  | Size.id2  | Size.id3
---- | --------- | --------- | ---------
1/1/1| L         | M         | S
1/2/1| S         | L         | L
1/3/1| M         | L         | S
...  | ...       | ...       | ...


df_color:

Date | Color.id1 | Color.id2| Color.id3
---- | --------- | ---------| ---------
1/1/1| RED       | BRN      | BLK
1/2/1| GRN       | BLK      | BLU
1/3/1| YEL       | ORA      | PUR
...  | ...       | ...      | ...

我知道tidyrspread()可能是完美的情况,但是我不确定如何真正完成这项工作。

  • 使用日期的key, value组合是什么?
  • 然后如何将其分为多个数据框?

谢谢!

2 个答案:

答案 0 :(得分:1)

好吧,你可以做:

df_shape <- df %>% distinct(Date, ID, Shape) %>%
  mutate(ID = paste0("Shape.id", ID)) %>%
  spread(ID, Shape)

df_size <- df %>% distinct(Date, ID, Size) %>%
  mutate(ID = paste0("Size.id", ID)) %>%
  spread(ID, Size)

df_color <- df %>% distinct(Date, ID, Color) %>%
  mutate(ID = paste0("Color.id", ID)) %>%
  spread(ID, Color)

答案 1 :(得分:1)

我将使用R附带的iris数据集来创建示例,并使用“ tidyverse”中的程序包。首先,我将创建一个date变量,以使iris看起来更像您的数据集。

library(purrr)
library(dplyr)
library(tidyr)
d <- mutate(iris, date = rep(1:50, 3))

创建一个variables对象,其中元素是您想要spread的变量,而元素的名称是数据框的名称:

variables <- setNames(names(iris)[1:4], paste0("df_", names(iris)[1:4]))
# df_Sepal.Length  df_Sepal.Width df_Petal.Length  df_Petal.Width 
#  "Sepal.Length"   "Sepal.Width"  "Petal.Length"   "Petal.Width" 

现在,我们使用map来遍历variables

out <- map(variables, function(f) {
  select(d, date, Species, f) %>%
    spread(key = Species, value = f) %>%
    rename_at(2:4, ~paste0(f, "_", .))
})

out如下所示:

str(out)
# List of 4
#  $ df_Sepal.Length:'data.frame':        50 obs. of  4 variables:
#   ..$ date                   : int [1:50] 1 2 3 4 5 6 7 8 9 10 ...
#   ..$ Sepal.Length_setosa    : num [1:50] 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
#   ..$ Sepal.Length_versicolor: num [1:50] 7 6.4 6.9 5.5 6.5 5.7 6.3 4.9 6.6 5.2 ...
#   ..$ Sepal.Length_virginica : num [1:50] 6.3 5.8 7.1 6.3 6.5 7.6 4.9 7.3 6.7 7.2 ...
#  $ df_Sepal.Width :'data.frame':        50 obs. of  4 variables:
#   ..$ date                  : int [1:50] 1 2 3 4 5 6 7 8 9 10 ...
#   ..$ Sepal.Width_setosa    : num [1:50] 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
#   ..$ Sepal.Width_versicolor: num [1:50] 3.2 3.2 3.1 2.3 2.8 2.8 3.3 2.4 2.9 2.7 ...
#   ..$ Sepal.Width_virginica : num [1:50] 3.3 2.7 3 2.9 3 3 2.5 2.9 2.5 3.6 ...
#  $ df_Petal.Length:'data.frame':        50 obs. of  4 variables:
#   ..$ date                   : int [1:50] 1 2 3 4 5 6 7 8 9 10 ...
#   ..$ Petal.Length_setosa    : num [1:50] 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
#   ..$ Petal.Length_versicolor: num [1:50] 4.7 4.5 4.9 4 4.6 4.5 4.7 3.3 4.6 3.9 ...
#   ..$ Petal.Length_virginica : num [1:50] 6 5.1 5.9 5.6 5.8 6.6 4.5 6.3 5.8 6.1 ...
#  $ df_Petal.Width :'data.frame':        50 obs. of  4 variables:
#   ..$ date                  : int [1:50] 1 2 3 4 5 6 7 8 9 10 ...
#   ..$ Petal.Width_setosa    : num [1:50] 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
#   ..$ Petal.Width_versicolor: num [1:50] 1.4 1.5 1.5 1.3 1.5 1.3 1.6 1 1.3 1.4 ...
#   ..$ Petal.Width_virginica : num [1:50] 2.5 1.9 2.1 1.8 2.2 2.1 1.7 1.8 1.8 2.5 ...

您可以将out保留为数据帧列表,也可以使用

list2env(out, envir = globalenv())

将列表组件分配到全局环境中。