将列拆分为相邻的列,使用行名作为 R 中的新列名
Split columns into adjacent columns, use row name as new column name in R
我有一个数据框,其中包含两列识别信息和一列用连字符分隔的字母对:
df<-data.frame(
list = rep(1:3, each = 2),
set = rep(c("A","B"), times = 3),
item = c("ab-cd","ef-gh","ij-kl","mn-op","qr-st","uv-wx")
)
我一直在努力完成的是将数据框转换为以下形式,其中: 1. "list" 索引的单独行分别折叠成一行; 2. "item" 列以连字符作为分隔符拆分为相邻的列; 3. "set" 列作为结果列命名的基础。
df2 <- data.frame(
list = c(1:3),
A_1 = c("ab", "ij", "qr"),
A_2 = c("cd", "kl", "st"),
B_1 = c("ef", "mn", "uv"),
B_2 = c("gh", "op", "wx"))
我参考了一些以前发布的问题(特别是[此处])并尝试使用 BASE 转置函数以及各种绑定函数以及 reshape
包和 splitstackshape
包。 None 我的近似解决方案很优雅,我想知道是否有这样做的好方法。
一如既往,我非常感谢这里的社区提供的建议和反馈。
非常感谢@AnandaMahto:它可以通过先重塑然后拆分而不是相反的方式在一行中完成。
library(splitstackshape)
cSplit(dcast(as.data.table(df), list ~ set, value.var = "item"), c("A", "B"), "-")
我们可以使用 base R 和 reshape2 分两步完成。
首先,我们创建包含拆分项的列“1”和“2”。通常,我们不会使用数字字符作为列名的开头,但它为我们节省了稍后重命名结果列的步骤。
df[,c("1","2")] <- do.call(rbind,strsplit(as.character(df$item),"-"))
然后我们使用recast
:
res <- recast(data=df, list~set+variable, measure.var=c("1","2"))
res
list A_1 A_2 B_1 B_2
1 1 ab cd ef gh
2 2 ij kl mn op
3 3 qr st uv wx
为了完整起见,这在 Hadleyverse 中也能很好地工作:
library(dplyr)
library(tidyr)
df %>%
separate(item, 1:2) %>%
gather(val, item, -set, -list) %>%
mutate(set=paste(set, val, sep="_")) %>%
select(-val) %>%
spread(set, item)
# list A_1 A_2 B_1 B_2
# 1 1 ab cd ef gh
# 2 2 ij kl mn op
# 3 3 qr st uv wx
为了完整起见,这也适用于 Hadleyverse 的基本 R 克星,reshape
:
reshape(cbind(df[-3],
do.call(rbind, strsplit(as.character(df$item), "-"))),
direction = "wide", idvar = "list", timevar = "set")
# list 1.A 2.A 1.B 2.B
# 1 1 ab cd ef gh
# 3 2 ij kl mn op
# 5 3 qr st uv wx
(但是 dcast
+ cSplit
会更有效率和可读性)。
我有一个数据框,其中包含两列识别信息和一列用连字符分隔的字母对:
df<-data.frame(
list = rep(1:3, each = 2),
set = rep(c("A","B"), times = 3),
item = c("ab-cd","ef-gh","ij-kl","mn-op","qr-st","uv-wx")
)
我一直在努力完成的是将数据框转换为以下形式,其中: 1. "list" 索引的单独行分别折叠成一行; 2. "item" 列以连字符作为分隔符拆分为相邻的列; 3. "set" 列作为结果列命名的基础。
df2 <- data.frame(
list = c(1:3),
A_1 = c("ab", "ij", "qr"),
A_2 = c("cd", "kl", "st"),
B_1 = c("ef", "mn", "uv"),
B_2 = c("gh", "op", "wx"))
我参考了一些以前发布的问题(特别是[此处])并尝试使用 BASE 转置函数以及各种绑定函数以及 reshape
包和 splitstackshape
包。 None 我的近似解决方案很优雅,我想知道是否有这样做的好方法。
一如既往,我非常感谢这里的社区提供的建议和反馈。
非常感谢@AnandaMahto:它可以通过先重塑然后拆分而不是相反的方式在一行中完成。
library(splitstackshape)
cSplit(dcast(as.data.table(df), list ~ set, value.var = "item"), c("A", "B"), "-")
我们可以使用 base R 和 reshape2 分两步完成。
首先,我们创建包含拆分项的列“1”和“2”。通常,我们不会使用数字字符作为列名的开头,但它为我们节省了稍后重命名结果列的步骤。
df[,c("1","2")] <- do.call(rbind,strsplit(as.character(df$item),"-"))
然后我们使用recast
:
res <- recast(data=df, list~set+variable, measure.var=c("1","2"))
res
list A_1 A_2 B_1 B_2
1 1 ab cd ef gh
2 2 ij kl mn op
3 3 qr st uv wx
为了完整起见,这在 Hadleyverse 中也能很好地工作:
library(dplyr)
library(tidyr)
df %>%
separate(item, 1:2) %>%
gather(val, item, -set, -list) %>%
mutate(set=paste(set, val, sep="_")) %>%
select(-val) %>%
spread(set, item)
# list A_1 A_2 B_1 B_2
# 1 1 ab cd ef gh
# 2 2 ij kl mn op
# 3 3 qr st uv wx
为了完整起见,这也适用于 Hadleyverse 的基本 R 克星,reshape
:
reshape(cbind(df[-3],
do.call(rbind, strsplit(as.character(df$item), "-"))),
direction = "wide", idvar = "list", timevar = "set")
# list 1.A 2.A 1.B 2.B
# 1 1 ab cd ef gh
# 3 2 ij kl mn op
# 5 3 qr st uv wx
(但是 dcast
+ cSplit
会更有效率和可读性)。