2014-11-05 71 views
1

假設我有rownames這種凌亂的數據幀重塑dataframes

df<-data.frame(A=rnorm(2),B=rnorm(2),C=rnorm(2)) 
rownames(df)<-c('male','female') 
> df     
      A   B   C 
male 0.10138957 1.036535 2.0708251 
female 0.08524181 -1.140275 -0.3800585 

我想進入它以整齊的形式,使得列ABC被摺疊成一列,並有一個Gender的附加列。它看起來像這樣

> desired_df 
    where value Gender 
1 A 0.10138957 male 
2 A 0.08524181 female 
3 B 1.03653464 male 
4 B -1.14027549 female 
5 C 2.07082513 male 
6 C -0.38005851 female 

這裏是實現這一目標使用tidyr的一種方式。

desired_df<-gather(df,where,value) 
desired_df['Gender']<-rep(c('male','female'),nrow(df)/2) 

但我不得不以不雅的方式將行名轉換成列。我的問題是 - tidyrreshape有什麼其他功能會對此有所幫助?或者我可以撥打gather以完成不同的操作,以便在一行中實現此結果?

回答

4

您可以通過幾種方式獲得您的「desired_df」。這裏有一個以「dplyr」和「tidyr」我們一點更方便地組合的步驟:

library(tidyr) 
library(dplyr) 
df %>% cbind(rn = rownames(df)) %>% gather(where, value, A:C) 

或者,你可以從「reshape2」使用matrix方法melt

library(reshape2) 
melt(as.matrix(df)) 
#  Var1 Var2  value 
# 1 male A -1.58936590 
# 2 female A -2.11861101 
# 3 male B -0.04883463 
# 4 female B 1.77685001 
# 5 male C 0.22472189 
# 6 female C 1.35717680 

在基礎R,您可以使用stack,只是回收rownames

cbind(rn = rownames(df), stack(df)) 
#  rn  values ind 
# 1 male -1.58936590 A 
# 2 female -2.11861101 A 
# 3 male -0.04883463 B 
# 4 female 1.77685001 B 
# 5 male 0.22472189 C 
# 6 female 1.35717680 C 

或者有一些輕微的掛羊頭賣狗肉,利用的爲table小號data.frame方法,你可以這樣做:

data.frame(as.table(as.matrix(df))) 
#  Var1 Var2  Freq 
# 1 male A -1.58936590 
# 2 female A -2.11861101 
# 3 male B -0.04883463 
# 4 female B 1.77685001 
# 5 male C 0.22472189 
# 6 female C 1.35717680 
+1

我會避免使用'cbind()返回'這樣的 - 這是一個有點陷阱的,因爲你永遠不知道什麼'cbind()返回'會返回(矩陣或數據框?)。我會使用'data.frame()'來代替。 – hadley 2014-11-05 19:42:12

+0

@hadley,不知道我理解你的評論。 'gather'和'stack'都會返回'data.frame's,這意味着我們知道'cbind'會返回什麼。或者有''gather'不會返回我沒有想到的'data.frame'的機會。 – A5C1D2H2I1M1N2O1R2T1 2014-11-06 01:43:35

+0

我的意思是一般使用'cbind()'是有風險的,因爲它定義的語義很差(以同樣的方式避免使用'sapply()') – hadley 2014-11-06 19:15:14