假设(为了简化)我有一个包含一些控制与治疗数据的表:
Which, Color, Response, Count
Control, Red, 2, 10
Control, Blue, 3, 20
Treatment, Red, 1, 14
Treatment, Blue, 4, 21
对于每种颜色,我想要一行包含对照和治疗数据,即:
Color, Response.Control, Count.Control, Response.Treatment, Count.Treatment
Red, 2, 10, 1, 14
Blue, 3, 20, 4, 21
我想这样做的一种方法是在每个控件/处理子集上使用内部合并(在Color列上合并),但是有更好的方法吗?我在想重塑包或堆栈功能可以某种方式来做,但我不确定。
答案 0 :(得分:19)
使用重塑包。
首先,融化你的data.frame:
x <- melt(df)
然后演员:
dcast(x, Color ~ Which + variable)
根据您正在使用的reshape包的版本,可能是cast()
(重塑)或dcast()
(reshape2)
瞧。
答案 1 :(得分:6)
cast
包中的reshape
函数(不要与基础R中的reshape
函数混淆)可以执行此操作以及许多其他操作。见这里:http://had.co.nz/reshape/
答案 2 :(得分:6)
添加选项(多年后)....
基本R中的典型方法涉及reshape
函数(由于需要时间掌握的众多参数,这通常不受欢迎)。它对于较小的数据集来说是一个非常有效的函数,但并不总能很好地扩展。
reshape(mydf, direction = "wide", idvar = "Color", timevar = "Which")
# Color Response.Control Count.Control Response.Treatment Count.Treatment
# 1 Red 2 10 1 14
# 2 Blue 3 20 4 21
已经涵盖了来自&#34;重塑&#34;的cast
/ dcast
。和&#34; reshape2&#34; (现在,来自&#34; data.table&#34;的dcast.data.table
,在拥有大型数据集时尤其有用)。但也来自Hadleyverse,那里有&#34; tidyr&#34;,它与&#34; dplyr&#34;包:
library(tidyr)
library(dplyr)
mydf %>%
gather(var, val, Response:Count) %>% ## make a long dataframe
unite(RN, var, Which) %>% ## combine the var and Which columns
spread(RN, val) ## make the results wide
# Color Count_Control Count_Treatment Response_Control Response_Treatment
# 1 Blue 20 21 3 4
# 2 Red 10 14 2 1
另外需要注意的是,在即将推出的&#34; data.table&#34;版本中, dcast.data.table
函数应该能够处理此问题而无需先melt
你的数据。
data.table
的{{1}}实现允许您将多列转换为宽格式而不首先将其熔化,如下所示:
dcast
答案 3 :(得分:3)
Reshape确实可以将瘦的数据框(例如,从简单的SQL查询)转换为宽矩阵,并且非常灵活,但速度很慢。对于大量数据,非常非常慢。幸运的是,如果你只想转向一个固定的形状,那么编写一个小C函数来快速进行转换是相当容易的。
在我的例子中,使用3列和672,338行旋转瘦数据框需要34秒重塑,使用我的R代码需要25秒,使用C需要2.3秒。具有讽刺意味的是,C实现可能比我更容易编写(调整速度)R实施。
这是用于旋转浮点数的核心C代码。请注意,它假设您已经在调用C代码之前在R 中分配了正确大小的结果矩阵,这导致R-devel人员惊恐地颤抖:
#include <R.h>
#include <Rinternals.h>
/*
* This mutates the result matrix in place.
*/
SEXP
dtk_pivot_skinny_to_wide(SEXP n_row ,SEXP vi_1 ,SEXP vi_2 ,SEXP v_3 ,SEXP result)
{
int ii, max_i;
unsigned int pos;
int nr = *INTEGER(n_row);
int * aa = INTEGER(vi_1);
int * bb = INTEGER(vi_2);
double * cc = REAL(v_3);
double * rr = REAL(result);
max_i = length(vi_2);
/*
* R stores matrices by column. Do ugly pointer-like arithmetic to
* map the matrix to a flat vector. We are translating this R code:
* for (ii in 1:length(vi.2))
* result[((n.row * (vi.2[ii] -1)) + vi.1[ii])] <- v.3[ii]
*/
for (ii = 0; ii < max_i; ++ii) {
pos = ((nr * (bb[ii] -1)) + aa[ii] -1);
rr[pos] = cc[ii];
/* printf("ii: %d \t value: %g \t result index: %d \t new value: %g\n", ii, cc[ii], pos, rr[pos]); */
}
return(result);
}