因子列1并根据第1列的因子级别转置其他列的相应行

时间:2015-10-22 16:38:13

标签: sql r dataframe transpose

我有一个大型数据框,直接从SQL数据库导入,具有以下类型的结构(对于可重现的示例):

Data structure

我想要考虑前3列,'id','day'和'type'。这3列始终相互依赖并相应地分解。 对于因子列,我想将列'valueTitle'转换为行作为新的列标题,并将列'value'转换为正确的'valueTitle'下的行。看起来应该是这样的:

Desired output

可重复的例子:

id <- c(5,5,5,6,6,6,7,7,7) 
day <- c("01.01.2000", "01.01.2000", "01.01.2000", "01.01.2001", "01.01.2001", "01.01.2001", "01.01.2002", "01.01.2002", "01.01.2002") 
type <- c("green", "green", "green","orange","orange","orange", "blue", "blue", "blue")
valueTitle <- c("title1","title2","title3","title1","title2","title3","title1","title2","title3")
value <- c(0.2, 0.6, 0.9, 0.6, 0.9, 0.9, 2, 1, 7)
df <- data.frame(id, day, type, valueTitle, value) 
df$id<-as.factor(df$id)      
df

  id        day   type valueTitle value
1  5 01.01.2000  green     title1   0.2
2  5 01.01.2000  green     title2   0.6
3  5 01.01.2000  green     title3   0.9
4  6 01.01.2001 orange     title1   0.6
5  6 01.01.2001 orange     title2   0.9
6  6 01.01.2001 orange     title3   0.9
7  7 01.01.2002   blue     title1   2.0
8  7 01.01.2002   blue     title2   1.0
9  7 01.01.2002   blue     title3   7.0

我一直在寻找一种只使用矢量化操作的解决方案,但是对此很长时间以来并没有找到好方法。我只提出了以下解决方案,但是基于一个循环,这看起来很错误有很多原因:

m<-matrix(ncol=3,nrow=3); m<-as.data.frame(m);m # pretend I know the real size, in reality this is not fixed
for ( i in  min(levels(df$id)):max(levels(df$id))){ 
  m[(df$id==i), ]<-(df[ ,('value')])
}
m<-t(m)
df2<-data.frame(m)
colnames(df2)<-(levels(df$valueTitle))
df2 <- cbind(id=levels(df$id), df2[,1:ncol(df2)])
df2

   id        day   type title1 title2 title3
V1  5 01.01.2000   blue    0.2    0.6    0.9
V2  6 01.01.2001  green    0.6    0.9    0.9
V3  7 01.01.2002 orange    2.0    1.0    7.0

这是错误的,因为&#39;键入&#39;混淆了,无论哪种方式,这种方法都会导致许多潜在的错误。我的真实数据集很大,而且数量很多&#39; valueTitle&#39;可以根据不同的身份而有所不同。

你能否建议任何能更有效地执行因子并对这些数据进行转置操作的方法?

(如果有一种方法可以直接在SQL中执行此操作,那也很不错!)

2 个答案:

答案 0 :(得分:2)

我们可以使用dcast

library(reshape2)
dcast(df, id+day+type~valueTitle, value.var='value')

或来自spread的{​​{1}}来重塑&#39; long&#39;格式为&#39; wide&#39;。

tidyr

答案 1 :(得分:1)

使用PIVOT

CREATE TABLE #tab (
   id         INTEGER  NOT NULL
  ,[day]       DATE  NOT NULL
  ,type       VARCHAR(100)  NOT NULL
  ,valueTitle VARCHAR(60) NOT NULL
  ,value      NUMERIC(10,2) NOT NULL);

INSERT INTO #tab (id,[day],type,valueTitle,value) 
VALUES (5,'2000-01-01','green','title1',0.2), (5,'2000-01-01','green','title2',0.6),
(5,'2000-01-01','green','title3',0.9), (6,'2001-01-01','orange','title1',0.6),
(6,'2001-01-01','orange','title2',0.9),(6,'2001-01-01','orange','title3',0.9),
(7,'2002-01-01','blue','title1',2.0), (7,'2002-01-01','blue','title2',1.0),
(7,'2002-01-01','blue','title3',7.0);

SELECT id, [day], type,title1, title2, title3
FROM #tab
PIVOT (MAX(value)
       FOR valueTitle IN (title1, title2, title3)) p;

LiveDemo