2013-04-14 47 views
3

我一直在嘗試學習R一段時間,但還沒有得到我的知識,甚至一個體面的水平呢。我最終會到達那裏,但我現在處於困境之中,想知道你是否可以幫助我做一個快速的「轉型」型作品。R統計中簡單的數據透視表類型轉換

我有一個csv數據文件,其中包含以下數據字段的18,000,000行:人員ID,日期和值。它基本上是從一個仿真模型,並模擬貢獻的人讓到他們的儲蓄賬戶,如:

1,28/02/2013,19.49 
2,13/03/2013,16.68 
3,15/03/2013,20.34 
2,10/01/2014,28.43 
3,12/06/2014,38.13 
1,29/08/2014,68.46 
1,20/12/2013,20.51 

所以,你可以看到,有可能是在數據的多個ID,但每個日期和貢獻量一個人是獨一無二的。

我想對此進行改造,以便每個人都有一年的貢獻記錄。因此,例如上述的將成爲:

ID,2013,2014 
1,40.00,68.46 
2,16.68,28.43 
3,20.34,38.13 

我有一個大概的瞭解,我怎麼能解決這個問題:創建數據的另一列只用幾年,然後通過ID和年度總結加起來適合所有捐款到每個ID /年桶中。我只是不知道如何開始將它翻譯成R腳本。

任何指針/指導將不勝感激。

非常感謝和親切的問候。

+0

與1800萬行,你幾乎肯定希望看看'data.table'解決方案(用於讀取數據以及重塑) –

回答

7

這裏有幾個可能性:

動物園包read.zoozoo package可以產生多變量時間序列每系列的一列,即每ID一列。我們定義yr從索引列中獲取年份,然後在我們讀入時使用split=參數分割ID。我們使用aggregate=sum來聚合剩餘的列 - 這裏只有一列。我們使用text = Lines來保持下面的代碼自身包含,但是有一個真實的文件,我們會用"myfile"代替它。最後一行轉換結果。如果可以在列中而不是在行中有人,我們可以刪除該行。

Lines <- "1,28/02/2013,19.49 
2,13/03/2013,16.68 
3,15/03/2013,20.34 
2,10/01/2014,28.43 
3,12/06/2014,38.13 
1,29/08/2014,68.46 
1,20/12/2013,20.51 
" 
library(zoo) 

# given a Date string, x, output the year 
yr <- function(x) floor(as.numeric(as.yearmon(x, "%d/%m/%Y"))) 

# read in data, reshape & aggregate 
z <- read.zoo(text = Lines, sep = ",", index = 2, FUN = yr, 
    aggregate = sum, split = 1)  

# transpose (optional) 
tz <- data.frame(ID = colnames(z), t(z), check.names = FALSE) 

隨着發佈的數據,我們得到以下結果:

> tz 
    ID 2013 2014 
1 1 40.00 68.46 
2 2 16.68 28.43 
3 3 20.34 38.13 

?read.zoo,也是zoo-read小插曲。

reshape2包下面是使用reshape2包的第二溶液:

library(reshape2) 

# read in and fix up column names and Year 

DF <- read.table(text = Lines, sep = ",") ## 
colnames(DF) <- c("ID", "Year", "Value") ## 
DF$Year <- sub(".*/", "", DF$Year) ## 

dcast(DF, ID ~ Year, fun.aggregate = sum, value.var = "Value") 

結果是:

ID 2013 2014 
1 1 40.00 68.46 
2 2 16.68 28.43 
3 3 20.34 38.13 

重塑功能這裏是不使用任何附加的溶液包。首先使用最後解決方案中標記爲##的三行讀取數據。這將產生DF。然後聚集的數據,從長重塑它廣泛形式並最終固定起來的列名:

Ag <- aggregate(Value ~., DF, sum) 
res <- reshape(Ag, direction = "wide", idvar = "ID", timevar = "Year") 
colnames(res) <- sub("Value.", "", colnames(res)) 

其產生這樣的:

> res 
    ID 2013 2014 
1 1 40.00 68.46 
2 2 16.68 28.43 
3 3 20.34 38.13 

tapply功能。這個解決方案也不使用插件包。從最後的解決方案使用Ag試試這個:

tapply(Ag$Value, Ag[1:2], sum) 

更新:小的改進和3個額外的解決方案。

+0

偉大的工作在那裏先生格洛騰迪克。解決方案2運行良好。解決方案1(動物園包)的工作類型,但它似乎給以v3前綴多個ID。和v4。再一次,我對R的知識很弱,所以不能完全確定這是否是我的數據或代碼的問題。第二個解決方案(使用reshape2包)完美運行。我只運行了幾次,但是我會離開並測試它並在主數據集上運行它。再次感謝你。這非常有幫助。這也很高興看到有一個解決方案(解決方案3),有優雅的堅持基本功能:) –

+0

需要一些可重現的評論。也許你可以準備一個小數據集來說明它,因爲答案中顯示的可重複示例中沒有v3/v4。 –

3

您描述的方法是合理的。從字符串到日期轉換日期字符串來回背可使用strptimestrftime(可能as.POSIXct來完成。一旦你的year列,你可以使用一些R中可用的工具,如data.tablebyddply。我喜歡最後一個的語法:

library(plyr) 
ddply(df, .(ID, year), summarise, total_per_year = sum(value)) 

這是假設你的基準日是df,並在您的數據的列被稱爲yearIDvalue請注意,對於大型數據集ddply可以成爲如果你確實需要原始的表現,你就會明白想要開始使用data.table

+1

非常好,「幾乎」到達那裏。謝謝保羅。事實證明,我沒有安裝plyr軟件包,所以對於任何人來說,請確保您從「軟件包>安裝軟件包」菜單中安裝「plyr」軟件包。所以現在唯一缺少的是每年將每一個單獨列。我現在要去嘗試格洛騰迪克先生的回答,並且看看這個展會是如何的。再次感謝。 –

+0

@TylerDurden對不起,我會將它添加到我的答案。 –