将数据从长格式重塑为宽格式
Reshape the data from long to wide format
我正在寻找 swift 将数据从长格式重塑为宽格式的方法。现在我尝试了一个带有嵌套for循环的代码,虽然工作完成了,但需要很长时间才能生成输出。
SN NN EE Service_tier
A B C economy
B C C economy
P Q R regular
Q S R regular
S R R regular
H I L economy
I J L economy
J K L economy
K L L economy
预期的输出如下
SN hop1 hop2 hop3 hop4 service_tier
A B C economy
P Q S R regular
H I J K L economy
目前以下代码可以完成工作。我确信有一种有效且干净的方法可以做到这一点。
for (i in 1:lasrow){
sn <- raw_d[i,1]
nn <- raw_d[i,2]
en <- raw_d[i,3]
lc <- 1
if(nn == en){
d[lr,lc]<-sn
d[lr,lc+1]<-nn
d[lr,lc+2]<-en
lr <- lr+1
}
else{
while(nn!=en){
d[lr,lc]<-sn
lc <- lc+1
next_d <- filter(raw_d,raw_d$SN==sn,raw_d$EN==en)
if(dim(next_d)[1]==0){
d[lr,lc]<-"broken bf"
lc <- lc+1
break
}else{
sn <- next_d$NN
nn <- next_d$NN
}
}
d[lr,lc]<-en
lr<-lr+1
}
}
一个选项是使用 rleid
从 data.table
创建一个唯一序列,gather
数据帧为长格式,从每个组中删除重复项,分配列名和 spread
它回到宽格式。
library(dplyr)
library(tidyr)
df %>%
mutate(row = data.table::rleid(Service_tier)) %>%
gather(key, value, -Service_tier, -row) %>%
group_by(row) %>%
filter(!duplicated(value)) %>%
mutate(key = c("SN", paste0("hop", 1:(n() - 1)))) %>%
spread(key, value) %>%
ungroup() %>%
select(-row) %>%
select(SN, starts_with("hop"), Service_tier)
# A tibble: 3 x 6
# SN hop1 hop2 hop3 hop4 Service_tier
# <chr> <chr> <chr> <chr> <chr> <fct>
#1 A B C NA NA economy
#2 H I J K L economy
#3 P Q S R NA regular
我们可以使用data.table
。将 'data.frame' 转换为 'dat.table'(setDT(df1)
,在 'Service_tier' 上按 rleid
分组,将 'SN' 的值更改为 first
按 'grp' 分组的元素,然后按 'Service_tier'、'SN' 分组,从 [=29] 中获取 Data.table 和 dcast
子集的 unique
元素=] 到 'wide' 格式
library(data.table)
dcast(setDT(df1)[, SN := first(SN), rleid(Service_tier)][,
unique(unlist(.SD)), .(SN, Service_tier)],
SN + Service_tier ~ paste0("hop", rowid(SN)), value.var = "V1", fill = "")
# SN Service_tier hop1 hop2 hop3 hop4
#1: A economy B C
#2: H economy I J K L
#3: P regular Q S R
数据
df1 <- structure(list(SN = c("A", "B", "P", "Q", "S", "H", "I", "J",
"K"), NN = c("B", "C", "Q", "S", "R", "I", "J", "K", "L"), EE = c("C",
"C", "R", "R", "R", "L", "L", "L", "L"), Service_tier = c("economy",
"economy", "regular", "regular", "regular", "economy", "economy",
"economy", "economy")), class = "data.frame", row.names = c(NA,
-9L))
这里的关键点是识别哪些行属于哪个组。 and 的答案都使用 rleid(Service_tier)
假设 Service_tier
的变化表示新组的开始。
这可能是样本数据集建议的,但不能被视为保证。恕我直言,Service_tier
与其说是键,不如说是属性。事实上,OP 正在他的代码片段中测试 NN == EE
以切换到新组。
在下面的 data.table 解决方案中,分组由 cumsum(shift(NN == EE, fill = TRUE))
确定,它测试 NN
和 EE
是否相等,将结果滞后到下一行,其中下一组开始,并通过使用 cumsum()
.
计数 TRUE
来枚举组
在简化版本(没有整形)中,跳数由 toString()
函数聚合:
library(data.table)
setDT(d)[, .(SN = first(SN), hops = toString(NN), Service_tier = first(Service_tier)),
by = .(grp = cumsum(shift(NN == EE, fill = TRUE)))][]
grp SN hops Service_tier
1: 1 A B, C economy
2: 2 P Q, S, R regular
3: 3 H I, J, K, L economy
为了从长格式重塑为宽格式,使用了dcast()
:
library(data.table)
library(magrittr) # piping used to improve readability
w <- setDT(d)[, .(SN = first(SN), hops = NN, Service_tier = first(Service_tier)),
by = .(grp = cumsum(shift(NN == EE, fill = TRUE)))] %>%
dcast(grp + ... ~ rowid(grp, prefix = "hop"), value.var = "hops", fill = "") %>%
setcolorder(c(1:2, 4:ncol(.), 3))
w
grp SN hop1 hop2 hop3 hop4 Service_tier
1: 1 A B C economy
2: 2 P Q S R regular
3: 3 H I J K L economy
setcolorder()
用于按照 OP 预期的顺序重新排列列。这是完成的 in-place,即没有复制整个数据对象。
数据
library(data.table)
d <- fread("SN NN EE Service_tier
A B C economy
B C C economy
P Q R regular
Q S R regular
S R R regular
H I L economy
I J L economy
J K L economy
K L L economy")
我正在寻找 swift 将数据从长格式重塑为宽格式的方法。现在我尝试了一个带有嵌套for循环的代码,虽然工作完成了,但需要很长时间才能生成输出。
SN NN EE Service_tier
A B C economy
B C C economy
P Q R regular
Q S R regular
S R R regular
H I L economy
I J L economy
J K L economy
K L L economy
预期的输出如下
SN hop1 hop2 hop3 hop4 service_tier
A B C economy
P Q S R regular
H I J K L economy
目前以下代码可以完成工作。我确信有一种有效且干净的方法可以做到这一点。
for (i in 1:lasrow){
sn <- raw_d[i,1]
nn <- raw_d[i,2]
en <- raw_d[i,3]
lc <- 1
if(nn == en){
d[lr,lc]<-sn
d[lr,lc+1]<-nn
d[lr,lc+2]<-en
lr <- lr+1
}
else{
while(nn!=en){
d[lr,lc]<-sn
lc <- lc+1
next_d <- filter(raw_d,raw_d$SN==sn,raw_d$EN==en)
if(dim(next_d)[1]==0){
d[lr,lc]<-"broken bf"
lc <- lc+1
break
}else{
sn <- next_d$NN
nn <- next_d$NN
}
}
d[lr,lc]<-en
lr<-lr+1
}
}
一个选项是使用 rleid
从 data.table
创建一个唯一序列,gather
数据帧为长格式,从每个组中删除重复项,分配列名和 spread
它回到宽格式。
library(dplyr)
library(tidyr)
df %>%
mutate(row = data.table::rleid(Service_tier)) %>%
gather(key, value, -Service_tier, -row) %>%
group_by(row) %>%
filter(!duplicated(value)) %>%
mutate(key = c("SN", paste0("hop", 1:(n() - 1)))) %>%
spread(key, value) %>%
ungroup() %>%
select(-row) %>%
select(SN, starts_with("hop"), Service_tier)
# A tibble: 3 x 6
# SN hop1 hop2 hop3 hop4 Service_tier
# <chr> <chr> <chr> <chr> <chr> <fct>
#1 A B C NA NA economy
#2 H I J K L economy
#3 P Q S R NA regular
我们可以使用data.table
。将 'data.frame' 转换为 'dat.table'(setDT(df1)
,在 'Service_tier' 上按 rleid
分组,将 'SN' 的值更改为 first
按 'grp' 分组的元素,然后按 'Service_tier'、'SN' 分组,从 [=29] 中获取 Data.table 和 dcast
子集的 unique
元素=] 到 'wide' 格式
library(data.table)
dcast(setDT(df1)[, SN := first(SN), rleid(Service_tier)][,
unique(unlist(.SD)), .(SN, Service_tier)],
SN + Service_tier ~ paste0("hop", rowid(SN)), value.var = "V1", fill = "")
# SN Service_tier hop1 hop2 hop3 hop4
#1: A economy B C
#2: H economy I J K L
#3: P regular Q S R
数据
df1 <- structure(list(SN = c("A", "B", "P", "Q", "S", "H", "I", "J",
"K"), NN = c("B", "C", "Q", "S", "R", "I", "J", "K", "L"), EE = c("C",
"C", "R", "R", "R", "L", "L", "L", "L"), Service_tier = c("economy",
"economy", "regular", "regular", "regular", "economy", "economy",
"economy", "economy")), class = "data.frame", row.names = c(NA,
-9L))
这里的关键点是识别哪些行属于哪个组。 rleid(Service_tier)
假设 Service_tier
的变化表示新组的开始。
这可能是样本数据集建议的,但不能被视为保证。恕我直言,Service_tier
与其说是键,不如说是属性。事实上,OP 正在他的代码片段中测试 NN == EE
以切换到新组。
在下面的 data.table 解决方案中,分组由 cumsum(shift(NN == EE, fill = TRUE))
确定,它测试 NN
和 EE
是否相等,将结果滞后到下一行,其中下一组开始,并通过使用 cumsum()
.
TRUE
来枚举组
在简化版本(没有整形)中,跳数由 toString()
函数聚合:
library(data.table)
setDT(d)[, .(SN = first(SN), hops = toString(NN), Service_tier = first(Service_tier)),
by = .(grp = cumsum(shift(NN == EE, fill = TRUE)))][]
grp SN hops Service_tier 1: 1 A B, C economy 2: 2 P Q, S, R regular 3: 3 H I, J, K, L economy
为了从长格式重塑为宽格式,使用了dcast()
:
library(data.table)
library(magrittr) # piping used to improve readability
w <- setDT(d)[, .(SN = first(SN), hops = NN, Service_tier = first(Service_tier)),
by = .(grp = cumsum(shift(NN == EE, fill = TRUE)))] %>%
dcast(grp + ... ~ rowid(grp, prefix = "hop"), value.var = "hops", fill = "") %>%
setcolorder(c(1:2, 4:ncol(.), 3))
w
grp SN hop1 hop2 hop3 hop4 Service_tier 1: 1 A B C economy 2: 2 P Q S R regular 3: 3 H I J K L economy
setcolorder()
用于按照 OP 预期的顺序重新排列列。这是完成的 in-place,即没有复制整个数据对象。
数据
library(data.table)
d <- fread("SN NN EE Service_tier
A B C economy
B C C economy
P Q R regular
Q S R regular
S R R regular
H I L economy
I J L economy
J K L economy
K L L economy")