在组内重塑数据 - 一行中的组
Reshape data within groups - groups in a single row
这是我的输入数据:
DeviceID ContentID Use
D1 C1 0.678491346
D1 C2 0.302147374
D2 C1 0.695790066
D2 C2 0.645849165
D3 C1 0.83503997
D3 C2 0.3622916
预期输出:
DeviceID ContentID_1 Use_1 ContentID_2 Use_2
D1 C1 0.678491346 C2 0.302147374
D2 C1 0.695790066 C2 0.645849165
D3 C1 0.83503997 C2 0.3622916
我尝试使用 reshape2 重塑它,但无法获得所需格式。
我试过了:
df %>%
group_by(DeviceID) %>%
mutate(rn = paste0("Content",row_number())) %>%
spread(rn, Use)
和
dcast(df,
DeviceID~ContentID,
value.var ="Use")
如有任何帮助,我们将不胜感激!
我们可以使用Reduce
和aggregate
按照上面给出的格式重新排列
data.frame(Reduce(cbind,aggregate(.~Device,dat,I)))[c(1,2,4,3,5)]
init V2 V4 V3 V5
1 D1 C1 0.678491346 C2 0.302147374
2 D2 C1 0.695790066 C2 0.645849165
3 D3 C1 0.83503997 C2 0.3622916
这是库 dplyr 的蛮力
map2_dfc(s<-dat%>%spread(Id,Content),names(s),~rev(stack(s,.y)))
ind values ind1 values1 ind2 values2
1 Device D1 C1 0.6784913 C2 0.3021474
2 Device D2 C1 0.6957901 C2 0.6458492
3 Device D3 C1 0.8350400 C2 0.3622916
df = read.table(text = "
DeviceId ContentID Use
D1 C1 0.678491346
D1 C2 0.302147374
D2 C1 0.695790066
D2 C2 0.645849165
D3 C1 0.83503997
D3 C2 0.3622916
", header=T, stringsAsFactors=F)
library(tidyverse)
df %>%
group_by(DeviceId) %>%
summarise_all(function(x) paste0(x, collapse = "_")) %>%
separate(ContentID, c("ID_1","ID_2"), sep="_") %>%
separate(Use, c("Use_1","Use_2"), sep="_")
# # A tibble: 3 x 5
# DeviceId ID_1 ID_2 Use_1 Use_2
# * <chr> <chr> <chr> <chr> <chr>
# 1 D1 C1 C2 0.678491346 0.302147374
# 2 D2 C1 C2 0.695790066 0.645849165
# 3 D3 C1 C2 0.83503997 0.3622916
发布我的解决方案:
library(splitstackshape)
library(tidyverse)
df %>%
group_by(DeviceId) %>%
summarise_all(function(x) paste0(x, collapse = "_")) %>%
cSplit(names(.)[-1], '_')
在评论中包含@AntoniosK 的建议。
library(data.table)
DT <- setDT(df)
使用您的 dcast 意图,您可以做到
Reduce(function(dtf1,dtf2) merge(dtf1,dtf2, by = "DeviceId"),
lapply( unique(DT$ContentID),
function(x){dcast(DT[ContentID == x],DeviceId + ContentID ~ ContentID ,value.var = "Use")} ))
DeviceId ContentID.x C1 ContentID.y C2
1: D1 C1 0.6784913 C2 0.3021474
2: D2 C1 0.6957901 C2 0.6458492
3: D3 C1 0.8350400 C2 0.3622916
自 v1.9.6(2015 年 9 月 19 日 CRAN)起,data.table
可以同时转换多个值列:
library(data.table)
dcast(setDT(df), DeviceID ~ rowid(DeviceID), value.var = c("ContentID", "Use"))
DeviceID ContentID_1 ContentID_2 Use_1 Use_2
1: D1 C1 C2 0.6784913 0.3021474
2: D2 C1 C2 0.6957901 0.6458492
3: D3 C1 C2 0.8350400 0.3622916
更改列顺序
结果包含预期的列,但顺序不同。 dcast()
创建按 value.var
分组的新列。
OP 没有指出确切的列顺序是否重要。但是,可以通过引用 更改列顺序 来准确重现预期结果,即,无需使用 setcolorder()
:
复制整个数据对象
cols <- c("ContentID", "Use")
wide <- dcast(setDT(df), DeviceID ~ rowid(DeviceID), value.var = cols)
new_col_order <- CJ(seq_len(uniqueN(df$ContentID)), cols)[, paste(V2, V1, sep = "_")]
setcolorder(wide, new_col_order)
wide
ContentID_1 Use_1 ContentID_2 Use_2 DeviceID
1: C1 0.6784913 C2 0.3021474 D1
2: C1 0.6957901 C2 0.6458492 D2
3: C1 0.8350400 C2 0.3622916 D3
CJ()
是行 ID 与 value.vars 的交叉连接,以按所需顺序创建列名。
我已提交 feature request on GitHub 以选择性地更改 dcast()
中列的顺序。
数据
library(data.table)
df <- fread(
" DeviceID ContentID Use
D1 C1 0.678491346
D1 C2 0.302147374
D2 C1 0.695790066
D2 C2 0.645849165
D3 C1 0.83503997
D3 C2 0.3622916"
)
这是我的输入数据:
DeviceID ContentID Use
D1 C1 0.678491346
D1 C2 0.302147374
D2 C1 0.695790066
D2 C2 0.645849165
D3 C1 0.83503997
D3 C2 0.3622916
预期输出:
DeviceID ContentID_1 Use_1 ContentID_2 Use_2
D1 C1 0.678491346 C2 0.302147374
D2 C1 0.695790066 C2 0.645849165
D3 C1 0.83503997 C2 0.3622916
我尝试使用 reshape2 重塑它,但无法获得所需格式。
我试过了:
df %>%
group_by(DeviceID) %>%
mutate(rn = paste0("Content",row_number())) %>%
spread(rn, Use)
和
dcast(df,
DeviceID~ContentID,
value.var ="Use")
如有任何帮助,我们将不胜感激!
我们可以使用Reduce
和aggregate
按照上面给出的格式重新排列
data.frame(Reduce(cbind,aggregate(.~Device,dat,I)))[c(1,2,4,3,5)]
init V2 V4 V3 V5
1 D1 C1 0.678491346 C2 0.302147374
2 D2 C1 0.695790066 C2 0.645849165
3 D3 C1 0.83503997 C2 0.3622916
这是库 dplyr 的蛮力
map2_dfc(s<-dat%>%spread(Id,Content),names(s),~rev(stack(s,.y)))
ind values ind1 values1 ind2 values2
1 Device D1 C1 0.6784913 C2 0.3021474
2 Device D2 C1 0.6957901 C2 0.6458492
3 Device D3 C1 0.8350400 C2 0.3622916
df = read.table(text = "
DeviceId ContentID Use
D1 C1 0.678491346
D1 C2 0.302147374
D2 C1 0.695790066
D2 C2 0.645849165
D3 C1 0.83503997
D3 C2 0.3622916
", header=T, stringsAsFactors=F)
library(tidyverse)
df %>%
group_by(DeviceId) %>%
summarise_all(function(x) paste0(x, collapse = "_")) %>%
separate(ContentID, c("ID_1","ID_2"), sep="_") %>%
separate(Use, c("Use_1","Use_2"), sep="_")
# # A tibble: 3 x 5
# DeviceId ID_1 ID_2 Use_1 Use_2
# * <chr> <chr> <chr> <chr> <chr>
# 1 D1 C1 C2 0.678491346 0.302147374
# 2 D2 C1 C2 0.695790066 0.645849165
# 3 D3 C1 C2 0.83503997 0.3622916
发布我的解决方案:
library(splitstackshape)
library(tidyverse)
df %>%
group_by(DeviceId) %>%
summarise_all(function(x) paste0(x, collapse = "_")) %>%
cSplit(names(.)[-1], '_')
在评论中包含@AntoniosK 的建议。
library(data.table)
DT <- setDT(df)
使用您的 dcast 意图,您可以做到
Reduce(function(dtf1,dtf2) merge(dtf1,dtf2, by = "DeviceId"),
lapply( unique(DT$ContentID),
function(x){dcast(DT[ContentID == x],DeviceId + ContentID ~ ContentID ,value.var = "Use")} ))
DeviceId ContentID.x C1 ContentID.y C2
1: D1 C1 0.6784913 C2 0.3021474
2: D2 C1 0.6957901 C2 0.6458492
3: D3 C1 0.8350400 C2 0.3622916
自 v1.9.6(2015 年 9 月 19 日 CRAN)起,data.table
可以同时转换多个值列:
library(data.table)
dcast(setDT(df), DeviceID ~ rowid(DeviceID), value.var = c("ContentID", "Use"))
DeviceID ContentID_1 ContentID_2 Use_1 Use_2 1: D1 C1 C2 0.6784913 0.3021474 2: D2 C1 C2 0.6957901 0.6458492 3: D3 C1 C2 0.8350400 0.3622916
更改列顺序
结果包含预期的列,但顺序不同。 dcast()
创建按 value.var
分组的新列。
OP 没有指出确切的列顺序是否重要。但是,可以通过引用 更改列顺序 来准确重现预期结果,即,无需使用 setcolorder()
:
cols <- c("ContentID", "Use")
wide <- dcast(setDT(df), DeviceID ~ rowid(DeviceID), value.var = cols)
new_col_order <- CJ(seq_len(uniqueN(df$ContentID)), cols)[, paste(V2, V1, sep = "_")]
setcolorder(wide, new_col_order)
wide
ContentID_1 Use_1 ContentID_2 Use_2 DeviceID 1: C1 0.6784913 C2 0.3021474 D1 2: C1 0.6957901 C2 0.6458492 D2 3: C1 0.8350400 C2 0.3622916 D3
CJ()
是行 ID 与 value.vars 的交叉连接,以按所需顺序创建列名。
我已提交 feature request on GitHub 以选择性地更改 dcast()
中列的顺序。
数据
library(data.table)
df <- fread(
" DeviceID ContentID Use
D1 C1 0.678491346
D1 C2 0.302147374
D2 C1 0.695790066
D2 C2 0.645849165
D3 C1 0.83503997
D3 C2 0.3622916"
)