R根据多个唯一变量有条件地将数据框从长转换为宽
R Conditionally transform data frame from long to wide based on multiple unique variables
我知道这在 SO 上很常见 post 但我花了太多时间研究将数据框从长格式转换为宽格式的方法,但还没有找到合适的方法post(s) 指导我完成整个过程。我有一个结构类似于下面的 reprex 的数据框,但有 100 多行。基本上,相同的结构每 9 行重复一次,但变量不同。但是,为了尽可能保持 post 的可读性,我提供了数据框的前 9 行。请注意,每个 Id
都与 Name
和 Pos
相关。
library("reshape2")
test <- data.frame(
Id = c("9644", "14513", "9874",
"12363", "9673", "9538",
"9585", "23447", "40396"),
Pos = c("SG", "SF", "PF", "C", "PG", "SF",
"SG", "PF", "PG"),
Name = c("John", "James", "Bob", "Sam",
"Mark", "Andrew", "Bobby", "Elaine", "Jerry"),
Score = c(55.66, 43.82, 37.35, 40.59,
35.15, 27.45, 28.82, 28.95,
34.98),
Sal = c(60000, 60000, 60000, 60000,
60000, 60000, 60000, 60000,
60000),
Total = c(332.77, 332.77, 332.77, 332.77,
332.77, 332.77, 332.77, 332.77,
332.77),
TmNumber = c(1, 1, 1, 1, 1, 1, 1, 1, 1))
我想将我的列和变量转换成这种格式:
desiredDF <- data.frame(
TmNum = "1",
Id1 = "9644", Id2 = "14513", Id3 = "9874", Id4 = "12363",
Id5 = "9673", Id6 = "9538", Id7 = "9585", Id8 = "23447",
Id9 = "403396",
PG = "Mark", PG = "Jerry", SG = "John", SG = "Bobby",
SF = "James", SF = "Andrew", PF = "Bob", PF = "Elaine",
C = "Sam",
Score1 = "55.66", Score2 = "43.82", Score3 = "3735", Score4 = "40.59",
Score5 = "35.15", Score6 = "27.45", Score7 = "28.82", Score8 = "28.95",
Score9 = "34.98",
Sal = "60000",
Total = "332.77"
)
我尝试了以下代码(还有几次失败的尝试):
test2 <- dcast(test, TmNum ~ Pos, value.var = "Name")
> test2
TmNum C PF PG SF SG
1 1 1 2 2 2 2
谢谢!
尝试合并多个 dcast:
library(reshape2)
Ave <- function(lab, x, g, FUN = seq_along) paste0(lab, ave(format(x), g, FUN = FUN))
L <- list(
dcast(data = transform(test, ID = Ave("Id", Id, TmNumber)),
TmNumber ~ ID, value.var = "Id"),
dcast(data = transform(test, Pos = Ave("", Pos, TmNumber, make.unique)),
TmNumber ~ Pos, value.var = "Name"),
dcast(data = transform(test, SCORE = Ave("Score", Score, TmNumber)),
TmNumber + Sal + Total ~ SCORE, value.var = "Score"))
Reduce(function(x, y) merge(x, y, by = 1), L)
给予:
TmNumber Id1 Id2 Id3 Id4 Id5 Id6 Id7 Id8 Id9 C PF PF.1 PG
1 1 9644 14513 9874 12363 9673 9538 9585 23447 40396 Sam Bob Elaine Mark
PG.1 SF SF.1 SG SG.1 Sal Total Score1 Score2 Score3 Score4 Score5
1 Jerry James Andrew John Bobby 60000 332.77 55.66 43.82 37.35 40.59 35.15
Score6 Score7 Score8 Score9
1 27.45 28.82 28.95 34.98
我知道这在 SO 上很常见 post 但我花了太多时间研究将数据框从长格式转换为宽格式的方法,但还没有找到合适的方法post(s) 指导我完成整个过程。我有一个结构类似于下面的 reprex 的数据框,但有 100 多行。基本上,相同的结构每 9 行重复一次,但变量不同。但是,为了尽可能保持 post 的可读性,我提供了数据框的前 9 行。请注意,每个 Id
都与 Name
和 Pos
相关。
library("reshape2")
test <- data.frame(
Id = c("9644", "14513", "9874",
"12363", "9673", "9538",
"9585", "23447", "40396"),
Pos = c("SG", "SF", "PF", "C", "PG", "SF",
"SG", "PF", "PG"),
Name = c("John", "James", "Bob", "Sam",
"Mark", "Andrew", "Bobby", "Elaine", "Jerry"),
Score = c(55.66, 43.82, 37.35, 40.59,
35.15, 27.45, 28.82, 28.95,
34.98),
Sal = c(60000, 60000, 60000, 60000,
60000, 60000, 60000, 60000,
60000),
Total = c(332.77, 332.77, 332.77, 332.77,
332.77, 332.77, 332.77, 332.77,
332.77),
TmNumber = c(1, 1, 1, 1, 1, 1, 1, 1, 1))
我想将我的列和变量转换成这种格式:
desiredDF <- data.frame(
TmNum = "1",
Id1 = "9644", Id2 = "14513", Id3 = "9874", Id4 = "12363",
Id5 = "9673", Id6 = "9538", Id7 = "9585", Id8 = "23447",
Id9 = "403396",
PG = "Mark", PG = "Jerry", SG = "John", SG = "Bobby",
SF = "James", SF = "Andrew", PF = "Bob", PF = "Elaine",
C = "Sam",
Score1 = "55.66", Score2 = "43.82", Score3 = "3735", Score4 = "40.59",
Score5 = "35.15", Score6 = "27.45", Score7 = "28.82", Score8 = "28.95",
Score9 = "34.98",
Sal = "60000",
Total = "332.77"
)
我尝试了以下代码(还有几次失败的尝试):
test2 <- dcast(test, TmNum ~ Pos, value.var = "Name")
> test2
TmNum C PF PG SF SG
1 1 1 2 2 2 2
谢谢!
尝试合并多个 dcast:
library(reshape2)
Ave <- function(lab, x, g, FUN = seq_along) paste0(lab, ave(format(x), g, FUN = FUN))
L <- list(
dcast(data = transform(test, ID = Ave("Id", Id, TmNumber)),
TmNumber ~ ID, value.var = "Id"),
dcast(data = transform(test, Pos = Ave("", Pos, TmNumber, make.unique)),
TmNumber ~ Pos, value.var = "Name"),
dcast(data = transform(test, SCORE = Ave("Score", Score, TmNumber)),
TmNumber + Sal + Total ~ SCORE, value.var = "Score"))
Reduce(function(x, y) merge(x, y, by = 1), L)
给予:
TmNumber Id1 Id2 Id3 Id4 Id5 Id6 Id7 Id8 Id9 C PF PF.1 PG
1 1 9644 14513 9874 12363 9673 9538 9585 23447 40396 Sam Bob Elaine Mark
PG.1 SF SF.1 SG SG.1 Sal Total Score1 Score2 Score3 Score4 Score5
1 Jerry James Andrew John Bobby 60000 332.77 55.66 43.82 37.35 40.59 35.15
Score6 Score7 Score8 Score9
1 27.45 28.82 28.95 34.98