我有数据存储在数据框中
CST M QS
501 1204315 1
501 1204324 1
501 6041541 2
501 7508226 1
501 7509677 1
501 7514622 1
503 7511601 2
507 6961200 2
507 7514100 2
507 7522029 1
509 7512374 1
509 7516799 2
511 419110 0.5
511 6000832 5
511 6960800 3.33
511 7010000 2
511 7508229 2.5
511 7508307 2
511 7515126 2
现在,我想基于CST更改此数据,不同的M必须存储在不同的列中。这些列应该是动态的,这样CST只能有1 M或者可以是10或20或无限,因此必须使用M1,M2,M3等生成许多列。必须使用基于sum(M)
的值的总和来显示QS示例输出如下
cst M1 M2 M3 M4 M5 M6 M7 Total
501 1204315 1204324 6041541 7508226 7509677 7514622 7
503 7511601 2
507 6961200 7514100 7522029 5
509 7512374 7516799 3
511 419110 6000832 6960800 7010000 7508229 7508307 7515126 17.33
我使用了transpose(),它只是将行转换为列。但这不会解析为我想要的预期输出。
我已尝试将data.table函数用作dt[,sum(QS),by="CST"]
,但无法在不同的列中显示M及其。
提前致谢。
答案 0 :(得分:3)
我们可以使用data.table
。我们将'data.frame'转换为'data.table'(setDT(df1)
),按'CST'分组,我们得到“QS”的行序列(1:.N
)和sum
“,分配(:=
)输出以创建两列(”N“,”总计“)。然后,我们使用dcast
将long
转换为wide
格式。
library(data.table)
setDT(df1)[, c("N", "Total") := list(paste0("M", 1:.N), sum(QS)), CST]
dcast(df1, CST+Total~N, value.var='M')
# CST Total M1 M2 M3 M4 M5 M6 M7
#1: 501 7.00 1204315 1204324 6041541 7508226 7509677 7514622 NA
#2: 503 2.00 7511601 NA NA NA NA NA NA
#3: 507 5.00 6961200 7514100 7522029 NA NA NA NA
#4: 509 3.00 7512374 7516799 NA NA NA NA NA
#5: 511 17.33 419110 6000832 6960800 7010000 7508229 7508307 7515126
或者我们使用与dplyr/tidyr
library(dplyr)
library(tidyr)
df1 %>%
group_by(CST) %>%
mutate(Total=sum(QS), N=row_number()) %>%
select(-QS) %>%
spread(N, M)
如果我们需要订单中的列,我们可以将“N”转换为factor
并指定levels
setDT(df2)[, c("N", "Total") := list(paste0("M", 1:.N), sum(QS)), CST]
df2[, N:= factor(N, levels=unique(N))]
dcast(df2, CST+Total~N, value.var="M")
df2 <- structure(list(CST = c(501L, 501L, 501L, 501L, 501L,
501L, 501L,
501L, 501L, 501L, 501L, 501L, 503L, 507L, 507L, 507L, 509L, 509L,
511L, 511L, 511L, 511L, 511L, 511L, 511L), M = c(1204315L, 1204324L,
6041541L, 7508226L, 7509677L, 7434399L, 7843392L, 7834393L, 8343999L,
3439242L, 3434323L, 7514622L, 7511601L, 6961200L, 7514100L, 7522029L,
7512374L, 7516799L, 419110L, 6000832L, 6960800L, 7010000L, 7508229L,
7508307L, 7515126L), QS = c(1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
1, 2, 2, 2, 1, 1, 2, 0.5, 5, 3.33, 2, 2.5, 2, 2)),
.Names = c("CST",
"M", "QS"), class = "data.frame", row.names = c(NA, -25L))