2015-10-22 26 views
1

我有一个大的数据帧,从SQL数据库直接输入与以下类型的结构(用于再现的实施例):因子塔1和转置其他列的相应的行1

Data structure

我想要分析前3列'id','day'和'type'。这3列总是相互依赖并相应地分解。 对于因式分解列,我想将列'valueTitle'转换为行以成为新的列标题并将列'值'转换为正确的'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 

因为“型”混合起来这是错误的,无论哪种方式,这种方法会导致很多潜在的错误。我的真实数据集很大,'valueTitle'的数量因不同'id'而异。

你能提出任何方法能更有效地执行这些数据的因子和转置操作吗?

(如果没有做到这一点直接在SQL它会是不错呢!方法)

回答

2

我们可以使用dcast

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

或者spreadtidyr从“长”格式,以重塑'宽'。

library(tidyr) 
spread(df, valueTitle, value) 
+0

谢谢! dcast()在一些额外的工作后工作,我必须创建新的表,其中每个'valueTitle'对应的整数索引,因为'valueTitle'中有重复的内容,显然dcast()在处理非唯一参数时遇到问题。我将很快发布解决方案。 – DianaLog

+1

@DianaLog在这种情况下,我们需要通过分组'valueTitle'创建一个序列列,然后使用'dcast' – akrun

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

相关问题