在R中的相同数据框中绑定具有相似列名的列

时间:2013-04-04 05:19:04

标签: r

我有一个看起来像这样的数据框:

df <- data.frame(0:2, 1:3, 2:4, 5:7, 6:8, 2:4, 0:2, 1:3, 2:4)
colnames(df) <- rep(c('a', 'b', 'c'), 3)
> df
  a b c a b c a b c
1 0 1 2 5 6 2 0 1 2
2 1 2 3 6 7 3 1 2 3
3 2 3 4 7 8 4 2 3 4

有多个列具有相同的名称。我想重新排列数据框,以便具有相同名称的列组合成它们自己的超级列,这样只剩下唯一的列名,例如:

> df
  a b c
1 0 1 2
2 1 2 3
3 2 3 4
4 5 6 2
5 6 7 3
6 7 8 4
7 0 1 2
8 1 2 3
9 2 3 4

有关如何做到这一点的任何想法?提前谢谢!

5 个答案:

答案 0 :(得分:9)

我想这就是诀窍。

<强>解释

df[,names(df) == 'a']将选择名为a

的所有列

unlist会将上面的列转换为1个单向量

unname将删除一些给予这些向量的迷路rownames。

unique(names(df))会在df

中为您提供唯一的列名称

sapply会将内联函数应用于unique(names(df))

的所有值
> df
  a b c a b c a b c
1 0 1 2 5 6 2 0 1 2
2 1 2 3 6 7 3 1 2 3
3 2 3 4 7 8 4 2 3 4
> sapply(unique(names(df)), function(x) unname(unlist(df[,names(df)==x])))
      a b c
 [1,] 0 1 2
 [2,] 1 2 3
 [3,] 2 3 4
 [4,] 5 6 2
 [5,] 6 7 3
 [6,] 7 8 4
 [7,] 0 1 2
 [8,] 1 2 3
 [9,] 2 3 4

答案 1 :(得分:5)

我的版本:

library(reshape)
as.data.frame(with(melt(df), split(value, variable)))
  a b c
1 0 1 2
2 1 2 3
3 2 3 4
4 0 1 2
5 1 2 3
6 2 3 4
7 0 1 2
8 1 2 3
9 2 3 4

在使用melt的步骤中,我转换了数据集:

> melt(df)
Using  as id variables
   variable value
1         a     0
2         a     1
3         a     2
4         b     1
5         b     2
6         b     3
7         c     2
8         c     3
9         c     4
10        a     0
11        a     1
12        a     2
13        b     1
14        b     2
15        b     3
16        c     2
17        c     3
18        c     4
19        a     0
20        a     1
21        a     2
22        b     1
23        b     2
24        b     3
25        c     2
26        c     3
27        c     4

然后,我使用valuevariable的每个唯一级别拆分split列:

$a
[1] 0 1 2 0 1 2 0 1 2

$b
[1] 1 2 3 1 2 3 1 2 3

$c
[1] 2 3 4 2 3 4 2 3 4

然后只需as.data.frame即可成为您需要的数据结构。

答案 2 :(得分:2)

使用%in%和一些不公开的

zz <- lapply(unique(names(df)), function(x,y) as.vector(unlist(df[which(y %in% x)])),y=names(df))
names(zz) <- unique(names(df))
as.data.frame(zz)
  a b c
1 0 1 2
2 1 2 3
3 2 3 4
4 5 6 2
5 6 7 3
6 7 8 4
7 0 1 2
8 1 2 3
9 2 3 4

答案 3 :(得分:2)

我会按列名对data.frame进行排序,取消列表,并在as.data.frame上使用matrix

A <- unique(names(df))[order(unique(names(df)))]
B <- matrix(unlist(df[, order(names(df))], use.names=FALSE), ncol = length(A))
B <- setNames(as.data.frame(B), A)
B
#   a b c
# 1 0 1 2
# 2 1 2 3
# 3 2 3 4
# 4 5 6 2
# 5 6 7 3
# 6 7 8 4
# 7 0 1 2
# 8 1 2 3
# 9 2 3 4

答案 4 :(得分:0)

我现在不在电脑前,所以无法测试,但是...... 。  这可能有用:

do.call(cbind, 
     lapply(names(df) function(x) do.call(rbind, df[, names(df) == x])) )