2011-05-04 109 views
156

我無法重新安排下面的數據幀:如何將數據從長格式轉換爲寬格式?

set.seed(45) 
dat1 <- data.frame(
    name = rep(c("firstName", "secondName"), each=4), 
    numbers = rep(1:4, 2), 
    value = rnorm(8) 
    ) 

dat1 
     name numbers  value 
1 firstName  1 0.3407997 
2 firstName  2 -0.7033403 
3 firstName  3 -0.3795377 
4 firstName  4 -0.7460474 
5 secondName  1 -0.8981073 
6 secondName  2 -0.3347941 
7 secondName  3 -0.5013782 
8 secondName  4 -0.1745357 

我想重塑它使每一個獨特的「名字」變量是rowname,與「價值」爲沿該行和意見「數字「作爲姓名。的排序是這樣的:

 name   1   2   3   4 
1 firstName 0.3407997 -0.7033403 -0.3795377 -0.7460474 
5 secondName -0.8981073 -0.3347941 -0.5013782 -0.1745357 

我已經看了meltcast和其他一些東西,但沒有人可以做的工作。

+1

可能重複(http://stackoverflow.com/questions/9617348/reshape-three-column-data-frame-to-matrix) – Frank 2013-10-08 20:53:22

+2

@Frank:此是一個更好的標題。 [tag:long-form]和[tag:wide-form]是使用的標準術語。通過搜索這些條款無法找到其他答案。 – smci 2014-04-11 05:21:53

+2

@smci擁有更好的標題並不是一個很好的理由不鏈接問題,是嗎?如果問題基本相同,未來訪問者聯繫起來會更好,因此所有答案都可以輕鬆找到。你可以在另一個方向標記重複,我想......另外,我不知道你爲什麼在這裏製作新的標籤。 – Frank 2014-04-11 16:49:41

回答

147

使用reshape功能:

reshape(dat1, idvar = "name", timevar = "numbers", direction = "wide") 
+9

+1,並且你不需要依賴外部包,因爲'reshape'帶有'stats'。更不用說它更快! =) – aL3xa 2011-05-05 00:07:44

+85

好運算出你需要的參數 – hadley 2011-05-05 01:40:56

+2

@hadley,yepp ...那是真的! =) – aL3xa 2011-05-05 09:45:15

59

您可以使用reshape()函數或重塑包中的melt()/cast()函數執行此操作。對於第二個選項,例如代碼

library(reshape) 
cast(dat1, name ~ numbers) 

或者使用reshape2

library(reshape2) 
dcast(dat1, name ~ numbers) 
+0

謝謝!我不敢相信我沒有看到這一點 - 我只是在張貼之前看過'演員',但卻無法讓它達到我想要的效果。 – Steve 2011-05-04 22:45:21

+7

+1使用'reshape2'獲得性能提升。 – Andrie 2011-05-06 11:56:54

+0

可能值得注意的是,如果您沒有清晰的「值」列,則僅使用'cast'或'dcast'將不會很好地工作。嘗試'dat < - data.frame(id = c(1,1,2,2),blah = c(8,4,7,6),index = c(1,2,1,2)); dcast(dat,id〜index); cast(dat,id〜index)',你不會得到你所期望的。你需要明確地注意'value/value.var' - 'cast(dat,id_index,value =「blah」)''和dcast(dat,id_index,value.var =「blah」)'for實例。 – thelatemail 2017-06-21 22:37:03

19

使用您的示例數據框中,我們可以:

xtabs(value ~ name + numbers, data = dat1) 
+0

這一個很好,但結果是格式表,它不像data.frame或data.table那樣容易處理,兩者都有大量的包 – cloudscomputes 2017-10-20 04:44:02

76

新的(2014年)tidyr包也是這樣做的,gather()/spread()melt/cast的條款。

library(tidyr) 
spread(dat1, key = numbers, value = value) 

github

tidyr是專陪整潔數據框架,並攜手在手與magrittrdplyr搭建數據分析了堅實的管道reshape2一個重新定義。

就像reshape2確實比重塑小,tidyr確實小於reshape2。它專門爲整理數據而設計,而不是整個reshape2所做的整形,或者重新整形的整體聚合。特別是,內置方法僅適用於數據幀,並且tidyr不提供邊距或聚合。

+1

只是想添加一個鏈接到[R Cookbook](http://www.cookbook-r.com/Manipulating_data/Converting_data_between_wide_and_long_format/)頁面,該頁面討論了來自'tidyr'和'reshape2'的這些函數的使用。它提供了很好的例子和解釋。 – Jake 2017-04-12 13:01:40

12

其他兩個選項:

基礎包:

df <- unstack(dat1, form = value ~ numbers) 
rownames(df) <- unique(dat1$name) 
df 

sqldf包:

library(sqldf) 
sqldf('SELECT name, 
     MAX(CASE WHEN numbers = 1 THEN value ELSE NULL END) x1, 
     MAX(CASE WHEN numbers = 2 THEN value ELSE NULL END) x2, 
     MAX(CASE WHEN numbers = 3 THEN value ELSE NULL END) x3, 
     MAX(CASE WHEN numbers = 4 THEN value ELSE NULL END) x4 
     FROM dat1 
     GROUP BY name') 
20

如果性能是一個問題的另一種選擇是使用data.table的延伸reshape2的融化& dcast功能

Reference: Efficient reshaping using data.tables

library(data.table) 

setDT(dat1) 
dcast(dat1, name ~ numbers, value.var = "value") 

#   name   1   2   3   4 
# 1: firstName 0.1836433 -0.8356286 1.5952808 0.3295078 
# 2: secondName -0.8204684 0.4874291 0.7383247 0.5757814 

而且,作爲data.table v1.9.6,我們可以澆鑄在多個列

## add an extra column 
dat1[, value2 := value * 2] 

## cast multiple value columns 
dcast(dat1, name ~ numbers, value.var = c("value", "value2")) 

#   name value_1 value_2 value_3 value_4 value2_1 value2_2 value2_3 value2_4 
# 1: firstName 0.1836433 -0.8356286 1.5952808 0.3295078 0.3672866 -1.6712572 3.190562 0.6590155 
# 2: secondName -0.8204684 0.4874291 0.7383247 0.5757814 -1.6409368 0.9748581 1.476649 1.1515627 
+1

'data.table'方法是最好的!非常高效......當名稱是30-40列的組合時,您將看到不同之處! – 2017-08-31 12:06:44

+2

我個人認爲這是最佳答案 – cloudscomputes 2017-10-20 04:37:47

5

使用基礎R aggregate功能:

aggregate(value ~ name, dat1, I) 

# name   value.1 value.2 value.3 value.4 
#1 firstName  0.4145 -0.4747 0.0659 -0.5024 
#2 secondName -0.8259 0.1669 -0.8962 0.1681 
+0

爲什麼使用粘貼功能而不是'I'(身份識別功能)? – Onyambu 2017-12-25 04:04:40

1

來自Win-Vector的天才數據科學家有非常強大的新軟件包(製作的人,seplyrreplyr),稱爲cdata。它實現了this document以及blog post中描述的「協調數據」原則。我們的想法是,無論您如何組織數據,應該可以使用「數據座標」系統來識別各個數據點。下面是由約翰·山最近博客文章摘錄:

整個系統是基於兩個基本或運營商 CDATA :: moveValuesToRowsD()和CDATA :: moveValuesToColumnsD()。這些 運算符具有主軸,非主軸,單熱編碼,轉置,移動多行和多列以及許多其他轉換,如簡單的特殊 個案。

根據cdata基元編寫許多不同的操作是很容易的。這些運算符可以使用內存或大數據規模(使用數據庫和Apache Spark;對於大數據使用cdata :: moveValuesToRowsN()和cdata :: moveValuesToColumnsN() 變體)。變換由控制表控制,該控制表本身是變換的圖形(或圖形)。

我們將首先構建控制表(詳見blog post),然後執行將數據從行移動到列。的[重塑三列的數據幀到矩陣]

library(cdata) 
# first build the control table 
pivotControlTable <- buildPivotControlTableD(table = dat1, # reference to dataset 
         columnToTakeKeysFrom = 'numbers', # this will become column headers 
         columnToTakeValuesFrom = 'value', # this contains data 
         sep="_")       # optional for making column names 

# perform the move of data to columns 
dat_wide <- moveValuesToColumnsD(tallTable = dat1, # reference to dataset 
        keyColumns = c('name'),   # this(these) column(s) should stay untouched 
        controlTable = pivotControlTable# control table above 
        ) 
dat_wide 

#>   name numbers_1 numbers_2 numbers_3 numbers_4 
#> 1 firstName 0.3407997 -0.7033403 -0.3795377 -0.7460474 
#> 2 secondName -0.8981073 -0.3347941 -0.5013782 -0.1745357 
相關問題