重新排列数据框架:将某些行转换为列

17

我很不确定如何正确地给这个问题命名!

假设我有一个数据框d:

当前数据框:

d <- data.frame(sample = LETTERS[1:2], cat = letters[11:20], count = c(1:10))

   sample cat count
1       A   k     1
2       B   l     2
3       A   m     3
4       B   n     4
5       A   o     5
6       B   p     6
7       A   q     7
8       B   r     8
9       A   s     9
10      B   t    10

我正在尝试重新排列数据,使每个猫的值成为一个单独的列,样本仍然是一列(或成为行名称),计数将是新猫列中的值,在样本没有猫计数时为0。如下所示:

期望的数据框布局:

   sample   k   l   m   n   o   p   q   r   s   t
1       A   1   0   3   0   5   0   7   0   9   0
2       B   0   2   0   4   0   6   0   8   0  10

这个问题有什么最好的解决方法?

我已经做到了这一步:

for (i in unique(d$sample)) {
    s <- d[d$sample==i,]
    st <- as.data.frame(t(s[,3]))
    colnames(st) <- s$cat
    rownames(st) <- i
} 

即循环遍历原始数据框中的样本,并为每个样本子集转置。因此,在这种情况下,我得到

   k m o q s
 A 1 3 5 7 9

并且

   l n p r  t
 B 2 4 6 8 10

我卡在这里了。我尝试了许多用 merge, bind, apply 等方法,但是似乎都找不到正确的方法。另外,我不禁想知道上面那个循环是否完全必要 - 也许可以用 unstack 实现?

无需多言,我是R新手... 如果有人能帮我解决这个问题,我将非常感激!

PS 我试图重新排列数据框以便使值的绘制更加容易(即我想在表格格式的图中显示实际数据框)。

谢谢!


你想要进行的操作是从“长”变为“宽”。这个问题以前已经被问过和回答过很多次了。 - nograpes
1
抱歉。我已经在这里和谷歌上无尽地搜索过了,只是找不到完全符合我需要的东西(不知道如何准确称呼我所需的东西也没有帮助)。我会查找“长/宽”... - crs
3个回答

17
使用reshape2包中的dcast函数。
> dcast(d, sample~cat, fill=0)
  sample k l m n o p q r s  t
1      A 1 0 3 0 5 0 7 0 9  0
2      B 0 2 0 4 0 6 0 8 0 10
< p > 从基础库中,xtabs是另一种选择。

> xtabs(count~sample+cat, d)
      cat
sample  k  l  m  n  o  p  q  r  s  t
     A  1  0  3  0  5  0  7  0  9  0
     B  0  2  0  4  0  6  0  8  0 10

如果您希望输出为数据框,则可以尝试以下代码:
> as.data.frame.matrix(xtabs(count~sample+cat, d))
  k l m n o p q r s  t
A 1 0 3 0 5 0 7 0 9  0
B 0 2 0 4 0 6 0 8 0 10

嗨,这看起来很不错。但是,我应该提到,我正在寻找一种在标准(基本)R中完成此操作的方法...(因为这不是为我而做的)。有没有办法做到这一点?(即使更复杂?) - crs
1
哦,真是太好了!非常感谢!!!这正是我要找的东西!虽然我还不能投票,但你真是个好人 :) - crs
2
@crs,我刚刚为你的问题点了+1,所以你现在的声望值是16。现在你可以投票支持两个回答 :) - A5C1D2H2I1M1N2O1R2T1

12

使用基础R中的reshape函数:

nn<-reshape(d,timevar="cat",idvar="sample",direction="wide")
names(nn)[-1]<-as.character(d$cat)
nn[is.na(nn)]<-0
> nn
  sample k l m n o p q r s  t
1      A 1 0 3 0 5 0 7 0 9  0
2      B 0 2 0 4 0 6 0 8 0 10

谢谢,@Metrics - 这也可以!(我现在明白nograpes在他的评论中所指的“长”和“宽”了!)Jilber的解决方案看起来更简洁 - 否则有什么区别?感谢您的帮助!学到额外的东西总是好的。 - crs
1
@crs,两者的主要区别在于xtabsdcast只能有一个“值”变量转换为宽格式。例如,在对原始的“d”数据框进行一些小改动后,尝试Metrics代码的第一行:d$blah <- 11:20。现在尝试使用dcastxtabs进行相同操作。用dcast,在首先将数据"melt"之后,可以得到类似的输出。而用xtabs,则需要分别重塑变量并将它们绑定在一起。而且,reshape()非常快,特别是与当前实现的dcast相比。 - A5C1D2H2I1M1N2O1R2T1
1
指标:+1,但我不知道是否值得费力去重命名。在这种情况下,因为我在上面的评论中描述了扩展示例... - A5C1D2H2I1M1N2O1R2T1
@AnandaMahto - 艰难地发现了第一个差异 - 没有任何理解,直到现在(我以为只是我!)非常感谢您的解释!现在每个人都得到一个赞 - 非常感谢大家。 - crs

0
这里有一个可能会引起兴趣的 tidyverse 解决方案:
library(tidyr)

d %>%
  pivot_wider(names_from = cat, 
              values_from = count, 
              values_fill = 0)

# A tibble: 2 x 11
  sample     k     l     m     n     o     p     q     r     s     t
  <chr>  <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
1 A          1     0     3     0     5     0     7     0     9     0
2 B          0     2     0     4     0     6     0     8     0    10

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接