我有以下虚拟数据:
library(dplyr)
library(tidyr)
library(reshape2)
dt <- expand.grid(Year = 1990:2014, Product=LETTERS[1:8], Country = paste0(LETTERS, "I")) %>% select(Product, Country, Year)
dt$value <- rnorm(nrow(dt))
我选择了两个产品国家组合
sdt <- dt %>% filter((Product == "A" & Country == "AI") | (Product == "B" & Country =="EI"))
我希望每个组合并排看到这些值。我可以使用dcast
:
sdt %>% dcast(Year ~ Product + Country)
是否可以使用 tidyr 包中的spread
执行此操作?
答案 0 :(得分:58)
一种选择是创建一个新的&#39; Prod_Count&#39;加入&#39;产品&#39;和国家&#39; paste
之前的列,使用select
删除这些列,然后重新排列&#39; long&#39;广泛的&#39;使用spread
中的tidyr
。
library(dplyr)
library(tidyr)
sdt %>%
mutate(Prod_Count=paste(Product, Country, sep="_")) %>%
select(-Product, -Country)%>%
spread(Prod_Count, value)%>%
head(2)
# Year A_AI B_EI
#1 1990 0.7878674 0.2486044
#2 1991 0.2343285 -1.1694878
或者我们可以使用unite
中的tidyr
(来自@ beetroot&#39;评论)避免一些步骤,并像以前一样重塑。
sdt%>%
unite(Prod_Count, Product,Country) %>%
spread(Prod_Count, value)%>%
head(2)
# Year A_AI B_EI
# 1 1990 0.7878674 0.2486044
# 2 1991 0.2343285 -1.1694878
答案 1 :(得分:1)
对于当前的开发版本tidyr,可以通过一个函数调用(pivot_wider()
)来实现。
pivot_wider()
(对口:pivot_longer()
)的工作方式与spread()
类似。
但是,它提供了其他功能,例如使用多个键/名称列(和/或多个值列)。
为此,参数names_from
(指示从哪个列中获取新变量的名称)可以采用多个列名称(此处为Product
和Country
)
library("tidyr")
packageVersion("tidyr")
#> [1] '0.8.3.9000'
sdt %>%
pivot_wider(id_cols = Year, names_from = c(Product, Country)) %>%
head(2)
#> # A tibble: 2 x 3
#> Year A_AI B_EI
#> <int> <dbl> <dbl>
#> 1 1990 -2.08 -0.113
#> 2 1991 -1.02 -0.0546
答案 2 :(得分:0)
Base R解决方案:
# Concatenate grouping vector:
dt$PC <- paste0(dt$Product, "_", dt$Country)
# Spread the vectors by year:
dt2 <- reshape(dt[,c(!(names(dt) %in% c("Product", "Country")))],
idvar = "Year",
ids = unique(dt$Year),
direction = "wide",
timevar = "PC")
# Remove "value.", from the vector names:
names(dt2) <- gsub("value[.]", "", names(dt2))
数据:
dt <- expand.grid(Year = 1990:2014,
Product = LETTERS[1:8],
Country = paste0(LETTERS, "I"))
dt$value <- rnorm(nrow(dt))