合并具有相同名称 r 的列
merge columns that have the same name r
我在 R 中使用 mongodb 使用 mongolite 创建的数据集。
我得到一个如下所示的列表:
_id A B A B A B NA NA
1 a 1 b 2 e 5 NA NA
2 k 4 l 3 c 3 d 4
我想将数据集合并为如下所示:
_id A B
1 a 1
2 k 4
1 b 2
2 l 3
1 e 5
2 c 3
1 NA NA
2 d 4
最后一列中的 NAs
在那里,因为这些列是根据第一个条目命名的,如果后面的条目的列数多于该列,则不会为它们分配名称,(如果我得到对此也有帮助,这会很棒,但这不是我来这里的原因)。
此外,列数可能因数据集的不同子集而异。
我试过 melt()
但因为它是一个列表而不是数据框,所以它没有按预期工作,我试过 stack()
但它不起作用,因为列具有相同的名称和一些他们甚至没有名字。
我知道这是一个非常奇怪的情况,感谢您的帮助。
谢谢。
使用library(magrittr)
数据:
df <- fread("
_id A B A B A B NA NA
1 a 1 b 2 e 5 NA NA
2 k 4 l 3 c 3 d 4 ",header=T)
setDF(df)
代码:
df2 <- df[,-1]
odds<- df2 %>% ncol %>% {(1:.)%%2} %>% as.logical
even<- df2 %>% ncol %>% {!(1:.)%%2}
cbind(df[,1,drop=F],
A=unlist(df2[,odds]),
B=unlist(df2[,even]),
row.names=NULL)
结果:
# _id A B
# 1 1 a 1
# 2 2 k 4
# 3 1 b 2
# 4 2 l 3
# 5 1 e 5
# 6 2 c 3
# 7 1 <NA> NA
# 8 2 d 4
我们可以使用data.table
。假设 A 和 B 总是互相跟随。我在 header 中创建了一个包含 2 组 NA 的示例。使用grep我们可以找到那些fread
已经命名为V8等。使用R的向量回收,你可以一次重命名多个header。如果在您的情况下这些名称不同,请更改 grep 命令中的模式。然后我们通过 melt
融化数据
library(data.table)
df <- fread("
_id A B A B A B NA NA NA NA
1 a 1 b 2 e 5 NA NA NA NA
2 k 4 l 3 c 3 d 4 e 5",
header = TRUE)
df
_id A B A B A B A B A B
1: 1 a 1 b 2 e 5 <NA> NA <NA> NA
2: 2 k 4 l 3 c 3 d 4 e 5
# assuming A B are always following each other. Can be done in 1 statement.
cols <- names(df)
cols[grep(pattern = "^V", x = cols)] <- c("A", "B")
names(df) <- cols
# melt data (if df is a data.frame replace df with setDT(df)
df_melted <- melt(df, id.vars = 1,
measure.vars = patterns(c('A', 'B')),
value.name=c('A', 'B'))
df_melted
_id variable A B
1: 1 1 a 1
2: 2 1 k 4
3: 1 2 b 2
4: 2 2 l 3
5: 1 3 e 5
6: 2 3 c 3
7: 1 4 <NA> NA
8: 2 4 d 4
9: 1 5 <NA> NA
10: 2 5 e 5
感谢您的帮助,他们给了我很大的启发。
即使@Andre Elrico 提供了一个在可重现示例中更好地工作的解决方案,@phiver 提供了一个对我的整体问题更有效的解决方案。
通过同时使用这两种方法,我得出了以下结论。
library(data.table)
#The data were in a list of lists called list for this example
temp <- as.data.table(matrix(t(sapply(list, '[', seq(max(sapply(list, lenth))))),
nrow = m))
# m here is the number of lists in list
cols <- names(temp)
cols[grep(pattern = "^V", x = cols)] <- c("B", "A")
#They need to be the opposite way because the first column is going to be substituted with id, and this way they fall on the correct column after that
cols[1] <- "id"
names(temp) <- cols
l <- melt.data.table(temp, id.vars = 1,
measure.vars = patterns(c("A", "B")),
value.name = c("A", "B"))
如果我有超过 2 列需要这样操作,我也可以使用它。
我在 R 中使用 mongodb 使用 mongolite 创建的数据集。
我得到一个如下所示的列表:
_id A B A B A B NA NA
1 a 1 b 2 e 5 NA NA
2 k 4 l 3 c 3 d 4
我想将数据集合并为如下所示:
_id A B
1 a 1
2 k 4
1 b 2
2 l 3
1 e 5
2 c 3
1 NA NA
2 d 4
最后一列中的 NAs
在那里,因为这些列是根据第一个条目命名的,如果后面的条目的列数多于该列,则不会为它们分配名称,(如果我得到对此也有帮助,这会很棒,但这不是我来这里的原因)。
此外,列数可能因数据集的不同子集而异。
我试过 melt()
但因为它是一个列表而不是数据框,所以它没有按预期工作,我试过 stack()
但它不起作用,因为列具有相同的名称和一些他们甚至没有名字。
我知道这是一个非常奇怪的情况,感谢您的帮助。
谢谢。
使用library(magrittr)
数据:
df <- fread("
_id A B A B A B NA NA
1 a 1 b 2 e 5 NA NA
2 k 4 l 3 c 3 d 4 ",header=T)
setDF(df)
代码:
df2 <- df[,-1]
odds<- df2 %>% ncol %>% {(1:.)%%2} %>% as.logical
even<- df2 %>% ncol %>% {!(1:.)%%2}
cbind(df[,1,drop=F],
A=unlist(df2[,odds]),
B=unlist(df2[,even]),
row.names=NULL)
结果:
# _id A B
# 1 1 a 1
# 2 2 k 4
# 3 1 b 2
# 4 2 l 3
# 5 1 e 5
# 6 2 c 3
# 7 1 <NA> NA
# 8 2 d 4
我们可以使用data.table
。假设 A 和 B 总是互相跟随。我在 header 中创建了一个包含 2 组 NA 的示例。使用grep我们可以找到那些fread
已经命名为V8等。使用R的向量回收,你可以一次重命名多个header。如果在您的情况下这些名称不同,请更改 grep 命令中的模式。然后我们通过 melt
library(data.table)
df <- fread("
_id A B A B A B NA NA NA NA
1 a 1 b 2 e 5 NA NA NA NA
2 k 4 l 3 c 3 d 4 e 5",
header = TRUE)
df
_id A B A B A B A B A B
1: 1 a 1 b 2 e 5 <NA> NA <NA> NA
2: 2 k 4 l 3 c 3 d 4 e 5
# assuming A B are always following each other. Can be done in 1 statement.
cols <- names(df)
cols[grep(pattern = "^V", x = cols)] <- c("A", "B")
names(df) <- cols
# melt data (if df is a data.frame replace df with setDT(df)
df_melted <- melt(df, id.vars = 1,
measure.vars = patterns(c('A', 'B')),
value.name=c('A', 'B'))
df_melted
_id variable A B
1: 1 1 a 1
2: 2 1 k 4
3: 1 2 b 2
4: 2 2 l 3
5: 1 3 e 5
6: 2 3 c 3
7: 1 4 <NA> NA
8: 2 4 d 4
9: 1 5 <NA> NA
10: 2 5 e 5
感谢您的帮助,他们给了我很大的启发。 即使@Andre Elrico 提供了一个在可重现示例中更好地工作的解决方案,@phiver 提供了一个对我的整体问题更有效的解决方案。 通过同时使用这两种方法,我得出了以下结论。
library(data.table)
#The data were in a list of lists called list for this example
temp <- as.data.table(matrix(t(sapply(list, '[', seq(max(sapply(list, lenth))))),
nrow = m))
# m here is the number of lists in list
cols <- names(temp)
cols[grep(pattern = "^V", x = cols)] <- c("B", "A")
#They need to be the opposite way because the first column is going to be substituted with id, and this way they fall on the correct column after that
cols[1] <- "id"
names(temp) <- cols
l <- melt.data.table(temp, id.vars = 1,
measure.vars = patterns(c("A", "B")),
value.name = c("A", "B"))
如果我有超过 2 列需要这样操作,我也可以使用它。