2014-01-31 142 views
8

從我讀到的,*重塑2中的施放操作失去了他們的result_variable功能。 Hadley暗示爲此使用plyr(將多個結果列附加到輸入數據幀)。我將如何實現文檔例子...reshape2:聚合函數的多個結果?

aqm <- melt(airquality, id=c("month", "day"), na.rm=TRUE) 
cast(aqm, month ~ variable + result_variable, range) 

使用reshape2dcast)和plyrddply)?

+2

你是否還在開始時跑過名字(airquality)< - tolower(names(airquality))? –

+0

不,這些姓氏已經是小寫字母......沒有必要。 – mrcalvin

回答

13

由於'reshape2'和'plyr'包的靈活性,此問題有多個答案。我將展示最簡單的例子之一瞭解這裏:

library(reshape2) 
library(plyr) 

aqm <- melt(airquality, id=c("Month", "Day"), na.rm=TRUE) 
aqm_ply <- ddply(aqm, .(Month, variable), summarize, min=min(value), max=max(value)) 
aqm_melt <- melt(aqm_ply, id=c("Month", "variable"), variable.name="variable2") 
dcast(aqm_melt, Month ~ variable + variable2) 

# Month Ozone_min Ozone_max Solar.R_min Solar.R_max Wind_min Wind_max Temp_min Temp_max 
# 1  5   1  115   8   334  5.7  20.1  56  81 
# 2  6  12  71   31   332  1.7  20.7  65  93 
# 3  7   7  135   7   314  4.1  14.9  73  92 
# 4  8   9  168   24   273  2.3  15.5  72  97 
# 5  9   7  96   14   259  2.8  16.6  63  93 

步驟1:讓我們把它分解爲若干步驟。首先,讓我們單獨定義'aqm',並從融化的數據中進行工作。這會讓這個例子更容易理解。

aqm <- melt(airquality, id=c("Month", "Day"), na.rm=TRUE) 

#  Month Day variable value 
# 1  5 1 Ozone 41.0 
# 2  5 2 Ozone 36.0 
# 3  5 3 Ozone 12.0 
# 4  5 4 Ozone 18.0 
# ... 
# 612  9 30  Temp 68.0 

步驟2:現在,我們要以取代「最小值」和「最大值」列中的「價值」欄。我們可以使用'plyr'軟件包中的'ddply'功能來實現這一點。爲此,我們使用'ddply'函數(數據幀作爲輸入,數據幀作爲輸出,因此「dd」-ply)。我們首先指定數據。

ddply(aqm, 

然後我們指定我們想要用來分組數據的變量'Month'和'variable'。我們使用.函數直接引用這些變量,而不是引用它們包含的值。

ddply(aqm, .(Month, variable), 

現在我們需要選擇一個聚合函數。我們在這裏選擇summarize函數,因爲我們有我們不希望包含在最終數據中的列(「日」和「值」)。 summarize函數將刪除所有原始的非分組列。

ddply(aqm, .(Month, variable), summarize, 

最後,我們指定每個組的計算。我們可以參考原始數據框('aqm')的列,儘管它們不會包含在我們的最終數據框中。這是它的外觀:

aqm_ply <- ddply(aqm, .(Month, variable), summarize, min=min(value), max=max(value)) 

# Month variable min max 
# 1  5 Ozone 1.0 115.0 
# 2  5 Solar.R 8.0 334.0 
# 3  5  Wind 5.7 20.1 
# 4  5  Temp 56.0 81.0 
# 5  6 Ozone 12.0 71.0 
# 6  6 Solar.R 31.0 332.0 
# 7  6  Wind 1.7 20.7 
# 8  6  Temp 65.0 93.0 
# 9  7 Ozone 7.0 135.0 
# 10  7 Solar.R 7.0 314.0 
# 11  7  Wind 4.1 14.9 
# 12  7  Temp 73.0 92.0 
# 13  8 Ozone 9.0 168.0 
# 14  8 Solar.R 24.0 273.0 
# 15  8  Wind 2.3 15.5 
# 16  8  Temp 72.0 97.0 
# 17  9 Ozone 7.0 96.0 
# 18  9 Solar.R 14.0 259.0 
# 19  9  Wind 2.8 16.6 
# 20  9  Temp 63.0 93.0 

步驟3:我們可以看到,數據被大大減少,因爲ddply功能聚合了線。現在我們需要再次對數據進行融合,所以我們可以得到最終數據幀的第二個變量。請注意,我們需要指定一個新的參數variable.name,所以我們沒有兩列名爲「變量」。

aqm_melt <- melt(aqm_ply, id=c("Month", "variable"), variable.name="variable2") 

    # Month variable variable2 value 
# 1  5 Ozone  min 1.0 
# 2  5 Solar.R  min 8.0 
# 3  5  Wind  min 5.7 
# 4  5  Temp  min 56.0 
# 5  6 Ozone  min 12.0 
# ... 
# 37  9 Ozone  max 96.0 
# 38  9 Solar.R  max 259.0 
# 39  9  Wind  max 16.6 
# 40  9  Temp  max 93.0 

步驟4:我們可以通過我們的數據鑄造成最終的形式終於包裹了這一切。

dcast(aqm_melt, Month ~ variable + variable2) 

# Month Ozone_min Ozone_max Solar.R_min Solar.R_max Wind_min Wind_max Temp_min Temp_max 
# 1  5   1  115   8   334  5.7  20.1  56  81 
# 2  6  12  71   31   332  1.7  20.7  65  93 
# 3  7   7  135   7   314  4.1  14.9  73  92 
# 4  8   9  168   24   273  2.3  15.5  72  97 
# 5  9   7  96   14   259  2.8  16.6  63  93 

希望這個例子能給你足夠的理解,讓你開始。請注意,'plyr'軟件包的新數據框優化版本正在積極開發'dplyr'名稱,因此您可能希望在代碼變得更加完備後將其轉換爲新軟件包。

4

這是一個dplyr解決方案,利用了令人驚歎的%>%功能。它還使用了基本功能(),這個功能通常使用不足(恕我直言)。代碼是自我解釋的。

library(dplyr) 
airquality %>% 
    melt(c('Month', 'Day')) %>% 
    group_by(Month, variable) %>% 
    summarise(min = min(value, na.rm = T), max = max(value, na.rm = T)) %>% 
    reshape(timevar = 'variable', idvar = 'Month', direction = 'wide') %>% 
    arrange(Month) 
5

我認爲其他的答案應該有你在如何使用「plyr」或「dplyr」(我會鼓勵你繼續在尋找那個方向)條款的保護。

對於好玩,這是一個圍繞dcast的包裝,讓您指定多個功能。它不適用於返回多個值的函數(如range),它需要您使用命名的函數列表。

dcastMult <- function(data, formula, value.var = "value", 
        funs = list("min" = min, "max" = max)) { 
    require(reshape2) 
    if (is.null(names(funs)) | any(names(funs) == "")) stop("funs must be named") 
    Form <- formula(formula) 
    LHS <- as.character(Form[[2]]) 
    if (length(LHS) > 1) LHS <- LHS[-1] 
    temp <- lapply(seq_along(funs), function(Z) { 
    T1 <- dcast(data, Form, value.var = value.var, 
       fun.aggregate=match.fun(funs[[Z]]), fill = 0) 
    Names <- !names(T1) %in% LHS 
    names(T1)[Names] <- paste(names(T1)[Names], names(funs)[[Z]], sep = "_") 
    T1 
    }) 
    Reduce(function(x, y) merge(x, y), temp) 
} 

它看起來像一個有點亂,但結果是,你要堅持你熟悉的語法相同,同時獲得使用多個聚合函數。 funs參數的「名稱」用作結果名稱中的後綴。可以按預期指定匿名功能,例如maxSq = function(x) max(x)^2

dcastMult(aqm, month ~ variable, value.var="value", 
     funs = list("min" = min, "max" = max)) 
# month ozone_min solar.r_min wind_min temp_min ozone_max solar.r_max wind_max temp_max 
# 1  5   1   8  5.7  56  115   334  20.1  81 
# 2  6  12   31  1.7  65  71   332  20.7  93 
# 3  7   7   7  4.1  73  135   314  14.9  92 
# 4  8   9   24  2.3  72  168   273  15.5  97 
# 5  9   7   14  2.8  63  96   259  16.6  93 
+0

謝謝我真的很喜歡這個 – Nate

+0

這是一個非常不錯的解決方案,但是你可以將參數傳遞給'funs'或其他任何參數給'dcast()'調用嗎?它怎麼會變得更通用? – landroni

2

隨着recent commitdevelopment version of data.table v1.9.5,我們可以同時投多個value.var列(也包括fun.aggregate使用多個聚合函數)。請參閱?dcast瞭解更多信息以及示例部分。

下面是我們如何使用dcast

require(data.table) # v1.9.5+ 
dt = as.data.table(airquality) 
valvars = c("Ozone", "Solar.R", "Wind", "Temp") 
dcast(dt, Month ~ ., fun=list(min, max), na.rm=TRUE, value.var=valvars) 
# Month ._min_Ozone ._min_Solar.R ._min_Wind ._min_Temp ._max_Ozone ._max_Solar.R ._max_Wind 
# 1:  5   1    8  5.7   56   115   334  20.1 
# 2:  6   12   31  1.7   65   71   332  20.7 
# 3:  7   7    7  4.1   73   135   314  14.9 
# 4:  8   9   24  2.3   72   168   273  15.5 
# 5:  9   7   14  2.8   63   96   259  16.6 
# ._max_Temp 
# 1:   81 
# 2:   93 
# 3:   92 
# 4:   97 
# 5:   93 

可以放心地忽略這些警告。