将数据从长格式重塑为宽格式 - 不止一个变量

Reshape data from long to wide format - more than one variable

我正在尝试使用 中的 dcast 函数将我的数据从长公式重塑为宽公式。

objective 是在 value.var 参数中使用不同的变量,但 R 不允许我在其中使用多个值。

还有其他方法可以解决吗?我看过其他类似的问题,但找不到类似的例子。

这是我当前的数据集:

+---------+------+--------+--------------+------------+
| Country | Year | Growth | Unemployment | Population |
+---------+------+--------+--------------+------------+
| A       | 2015 |      2 |          8.3 |         40 |
| B       | 2015 |      3 |          9.2 |         32 |
| C       | 2015 |    2.5 |          9.1 |         30 |
| D       | 2015 |    1.5 |          6.1 |         27 |
| A       | 2016 |      4 |          8.1 |         42 |
| B       | 2016 |    3.5 |            9 |       32.5 |
| C       | 2016 |    3.7 |            9 |         31 |
| D       | 2016 |    3.1 |          5.3 |         29 |
| A       | 2017 |    4.5 |          8.1 |       42.5 |
| B       | 2017 |    4.4 |          8.4 |         33 |
| C       | 2017 |    4.3 |          8.5 |         30 |
| D       | 2017 |    4.2 |          5.2 |         30 |
+---------+------+--------+--------------+------------+

我的 objective 是将年份列传递给其余列(增长、失业和人口)。我正在使用下面的 dcast 函数。

data_wide <- dcast(world, country  ~ year,
     value.var=c("Growth","Unemployment","Population"))

理想的结果

+---------+-------------+-------------------+-----------------+-------------+-------------------+-----------------+
| Country | Growth_2015 | Unemployment_2015 | Population_2015 | Growth_2016 | Unemployment_2016 | Population_2016 |
+---------+-------------+-------------------+-----------------+-------------+-------------------+-----------------+
| A       |           2 |               8.3 |              40 |           4 |               8.1 |              42 |
| B       |           3 |               9.2 |              32 |         3.5 |                 9 |            32.5 |
| C       |         2.5 |               9.1 |              30 |         3.7 |                 9 |              31 |
| D       |         1.5 |               6.1 |              27 |         3.1 |               5.3 |              29 |
+---------+-------------+-------------------+-----------------+-------------+-------------------+-----------------+

如果您没有使用 dcast 解决方案,我个人认为 tidyr 更容易。

library(tidyr)
df <- df %>% 
     gather(key, value, -Country, -Year) %>%  
     unite(new.col, c(key, Year)) %>%   
     spread(new.col, value) 

结果

  Country Growth_2015 Growth_2016 Growth_2017 Population_2015 Population_2016 Population_2017 Unemployment_2015 Unemployment_2016 Unemployment_2017
1       A         2.0         4.0         4.5              40            42.0            42.5               8.3               8.1               8.1
2       B         3.0         3.5         4.4              32            32.5            33.0               9.2               9.0               8.4
3       C         2.5         3.7         4.3              30            31.0            30.0               9.1               9.0               8.5
4       D         1.5         3.1         4.2              27            29.0            30.0               6.1               5.3               5.2

这是

的作品

正在将所有值堆叠到一列中...

正在将变量名称和年份列合并为一个列...

然后将新栏目展开为宽格式

OP 给出的 dcast() 语句与最新版本的 data.table 包几乎完美配合,因为这些允许多个测量变量与 dcast()melt():

library(data.table)   # CRAN version 1.10.4
setDT(world)   # coerce to data.table
data_wide <- dcast(world, Country ~ Year, 
                   value.var = c("Growth", "Unemployment", "Population"))

data_wide
#   Country Growth_2015 Growth_2016 Growth_2017 Unemployment_2015 Unemployment_2016 Unemployment_2017 Population_2015
#1:       A         2.0         4.0         4.5               8.3               8.1               8.1              40
#2:       B         3.0         3.5         4.4               9.2               9.0               8.4              32
#3:       C         2.5         3.7         4.3               9.1               9.0               8.5              30
#4:       D         1.5         3.1         4.2               6.1               5.3               5.2              27
#   Population_2016 Population_2017
1:            42.0            42.5
2:            32.5            33.0
3:            31.0            30.0
4:            29.0            30.0

这与 的结果相同。


但是,OP 已为他的理想解决方案 请求了特定的列顺序,其中每年的不同度量变量组合在一起。

如果列的正确顺序很重要,有两种方法可以实现。第一种方法是使用 setcolorder():

适当地重新排序列
new_ord <- CJ(world$Year, c("Growth","Unemployment","Population"), 
              sorted = FALSE, unique = TRUE)[, paste(V2, V1, sep = "_")]
setcolorder(data_wide, c("Country", new_ord))

data_wide
#   Country Growth_2015 Unemployment_2015 Population_2015 Growth_2016 Unemployment_2016 Population_2016 Growth_2017
#1:       A         2.0               8.3              40         4.0               8.1            42.0         4.5
#2:       B         3.0               9.2              32         3.5               9.0            32.5         4.4
#3:       C         2.5               9.1              30         3.7               9.0            31.0         4.3
#4:       D         1.5               6.1              27         3.1               5.3            29.0         4.2
#   Unemployment_2017 Population_2017
#1:               8.1            42.5
#2:               8.4            33.0
#3:               8.5            30.0
#4:               5.2            30.0

请注意 cross join 函数 CJ() 用于创建向量的叉积。


实现所需列顺序的另一种方法是熔化和重铸:

molten <- melt(world, id.vars = c("Country", "Year"))
dcast(molten, Country ~ Year + variable)
#   Country 2015_Growth 2015_Unemployment 2015_Population 2016_Growth 2016_Unemployment 2016_Population 2017_Growth
#1:       A         2.0               8.3              40         4.0               8.1            42.0         4.5
#2:       B         3.0               9.2              32         3.5               9.0            32.5         4.4
#3:       C         2.5               9.1              30         3.7               9.0            31.0         4.3
#4:       D         1.5               6.1              27         3.1               5.3            29.0         4.2
#   2017_Unemployment 2017_Population
#1:               8.1            42.5
#2:               8.4            33.0
#3:               8.5            30.0
#4:               5.2            30.0