R 中的复杂数据重塑
Complex data reshaping in R
我有一个包含 3 列的数据框(摘录如下):
df <- data.frame(
id = c(1,1,1,2,2,2),
Year = c(2007, 2008, 2009, 2007, 2008, 2009),
A = c(5, 2, 3, 7, 5, 6),
B = c(10, 0, 50, 13, 17, 17)
)
df
我想要这个:
df_needed <- data.frame(
id= c(1, 2),
A_2007 = c(5, 7),
B_2007 = c(10, 13),
A_2008 = c(2, 5),
B_2008 = c(0, 17),
A_2009 = c(3, 6),
B_2009 = c(50, 17)
)
df_needed
我熟悉 reshape
和 tidyR
,但我认为他们无法管理这种转变。
是否有正确的方法来做到这一点,或者我需要使用自定义函数来做到这一点?
编辑:已编辑此示例以改进最终数据集中超过 1 条记录的示例。
尝试
library(dplyr)
library(tidyr)
gather(df, Var, Val, -Year) %>%
unite(YearVar, Var, Year) %>%
mutate(indx=1) %>%
spread(YearVar, Val)%>%
select(-indx)
# A_2007 A_2008 A_2009 B_2007 B_2008 B_2009
#1 5 2 3 10 0 50
更新
对于编辑,您可以更改 gather
中的变量
gather(df, Var, Val, A:B) %>%
unite(YearVar, Var, Year) %>%
spread(YearVar, Val)
# id A_2007 A_2008 A_2009 B_2007 B_2008 B_2009
#1 1 5 2 3 10 0 50
#2 2 7 5 6 13 17 17
这是一个可能的解决方案,使用 data.table
v >= 1.9.5
library(data.table)
dcast(setDT(df), . ~ Year, value.var = c("A", "B"))
# . 2007_A 2008_A 2009_A 2007_B 2008_B 2009_B
# 1: . 5 2 3 10 0 50
编辑:根据您的新数据集,只需将 id
添加到公式
dcast(setDT(df), id ~ Year, value.var = c("A", "B"))
# id 2007_A 2008_A 2009_A 2007_B 2008_B 2009_B
# 1: 1 5 2 3 10 0 50
# 2: 2 7 5 6 13 17 17
base R
中的另一个简单选项:
df_needed <- matrix(as.vector(t(df[, -1])), ncol=nrow(df)*(ncol(df)-1))
colnames(df_needed) <- paste(rep(colnames(df)[-1], nrow(df)), rep(df[, 1], e=ncol(df)-1), sep="_")
df_needed
# A_2007 B_2007 A_2008 B_2008 A_2009 B_2009
#[1,] 5 10 2 0 3 50
已编辑数据
df_split <- split(df, df$Year)
df_split <- lapply(df_split, function(df){colnames(df)[-1] <- paste(colnames(df)[-1], unique(df$Year), sep="_"); df <- df[, -1]; return(df)})
df_needed <- do.call("cbind", df_split)
colnames(df_needed) <- sub("^\d{4}\.","",colnames(df_needed))
df_needed
# A_2007 B_2007 A_2008 B_2008 A_2009 B_2009
#1 5 10 2 0 3 50
#4 7 13 5 17 6 17
Good ol' base::reshape
在这里工作正常。只需先创建一个虚拟 id 变量。
df$id <- 1
reshape(df, v.names = c("A", "B"), timevar = "Year", idvar = "id", direction = "wide")
# id A.2007 B.2007 A.2008 B.2008 A.2009 B.2009
# 1 1 5 10 2 0 3 50
如果您指定了 timevar
和 idvar
,为了节省一些输入,您 没有 来提供 v.names
:
reshape(df, timevar = "Year", idvar = "id", direction = "wide")
这也适用于编辑后的数据(碰巧已经有了 "id" 变量)。
# id A_2007 B_2007 A_2008 B_2008 A_2009 B_2009
# 1 1 5 10 2 0 3 50
# 2 2 7 13 5 17 6 17
您也可以使用 reshape2::recast
:
recast(df, id ~ variable + Year, id.var = 1:2)
我有一个包含 3 列的数据框(摘录如下):
df <- data.frame(
id = c(1,1,1,2,2,2),
Year = c(2007, 2008, 2009, 2007, 2008, 2009),
A = c(5, 2, 3, 7, 5, 6),
B = c(10, 0, 50, 13, 17, 17)
)
df
我想要这个:
df_needed <- data.frame(
id= c(1, 2),
A_2007 = c(5, 7),
B_2007 = c(10, 13),
A_2008 = c(2, 5),
B_2008 = c(0, 17),
A_2009 = c(3, 6),
B_2009 = c(50, 17)
)
df_needed
我熟悉 reshape
和 tidyR
,但我认为他们无法管理这种转变。
是否有正确的方法来做到这一点,或者我需要使用自定义函数来做到这一点?
编辑:已编辑此示例以改进最终数据集中超过 1 条记录的示例。
尝试
library(dplyr)
library(tidyr)
gather(df, Var, Val, -Year) %>%
unite(YearVar, Var, Year) %>%
mutate(indx=1) %>%
spread(YearVar, Val)%>%
select(-indx)
# A_2007 A_2008 A_2009 B_2007 B_2008 B_2009
#1 5 2 3 10 0 50
更新
对于编辑,您可以更改 gather
gather(df, Var, Val, A:B) %>%
unite(YearVar, Var, Year) %>%
spread(YearVar, Val)
# id A_2007 A_2008 A_2009 B_2007 B_2008 B_2009
#1 1 5 2 3 10 0 50
#2 2 7 5 6 13 17 17
这是一个可能的解决方案,使用 data.table
v >= 1.9.5
library(data.table)
dcast(setDT(df), . ~ Year, value.var = c("A", "B"))
# . 2007_A 2008_A 2009_A 2007_B 2008_B 2009_B
# 1: . 5 2 3 10 0 50
编辑:根据您的新数据集,只需将 id
添加到公式
dcast(setDT(df), id ~ Year, value.var = c("A", "B"))
# id 2007_A 2008_A 2009_A 2007_B 2008_B 2009_B
# 1: 1 5 2 3 10 0 50
# 2: 2 7 5 6 13 17 17
base R
中的另一个简单选项:
df_needed <- matrix(as.vector(t(df[, -1])), ncol=nrow(df)*(ncol(df)-1))
colnames(df_needed) <- paste(rep(colnames(df)[-1], nrow(df)), rep(df[, 1], e=ncol(df)-1), sep="_")
df_needed
# A_2007 B_2007 A_2008 B_2008 A_2009 B_2009
#[1,] 5 10 2 0 3 50
已编辑数据
df_split <- split(df, df$Year)
df_split <- lapply(df_split, function(df){colnames(df)[-1] <- paste(colnames(df)[-1], unique(df$Year), sep="_"); df <- df[, -1]; return(df)})
df_needed <- do.call("cbind", df_split)
colnames(df_needed) <- sub("^\d{4}\.","",colnames(df_needed))
df_needed
# A_2007 B_2007 A_2008 B_2008 A_2009 B_2009
#1 5 10 2 0 3 50
#4 7 13 5 17 6 17
Good ol' base::reshape
在这里工作正常。只需先创建一个虚拟 id 变量。
df$id <- 1
reshape(df, v.names = c("A", "B"), timevar = "Year", idvar = "id", direction = "wide")
# id A.2007 B.2007 A.2008 B.2008 A.2009 B.2009
# 1 1 5 10 2 0 3 50
如果您指定了 timevar
和 idvar
,为了节省一些输入,您 没有 来提供 v.names
:
reshape(df, timevar = "Year", idvar = "id", direction = "wide")
这也适用于编辑后的数据(碰巧已经有了 "id" 变量)。
# id A_2007 B_2007 A_2008 B_2008 A_2009 B_2009
# 1 1 5 10 2 0 3 50
# 2 2 7 13 5 17 6 17
您也可以使用 reshape2::recast
:
recast(df, id ~ variable + Year, id.var = 1:2)