2014-01-25 3 views
4

Есть ли простой способ (т.е. без использования «для» петель) сделать следующее:llply операция на несколько dataframes

У меня есть кадры пара данных. Я хочу использовать операцию plyr, чтобы суммировать их. В этом примере у меня есть два кадра данных: восток и запад, и я хочу обобщить оба из них с расходами и судебными разбирательствами по странам.

Вот кадры пример данных:

west <- data.frame(
    spend = sample(50:100,50,replace=T), 
    trials = sample(100:200,50,replace=T), 
    country = sample(c("usa","canada","uk"),50,replace = T) 
    ) 

east <- data.frame(
    spend = sample(50:100,50,replace=T), 
    trials = sample(100:200,50,replace=T), 
    country = sample(c("china","japan","skorea"),50,replace = T) 
    ) 

и объединенный список как dataframes:

combined <- c(west,east) 

То, что я хочу сделать, это операция ddply типа на обоих этих dataframes в то в то же время, и выход будет списком (по крайней мере, это кажется наиболее простым). Например, если бы я просто работать на одном dataframe, это было бы что-то вроде:

country.df <- ddply(west, .(country), summarise, 
    spend = sum(spend), 
    trials = sum(trials) 
) 

Но я хочу сделать это в масштабе. Я попытался с помощью похожий синтаксис в llply аргумента, но это не работает (у меня есть чувство, что я что-то болезненно очевидное отсутствующее):

countries.list <- llply(combined, .(country), summarise, 
    spend = sum(spend), 
    trials = sum(trials) 
) 

Это возвращает ошибку: «Ошибка в FUN (X [[1L ]], ...): попытка применить нефункцию "

... Я могу придумать способ сделать это, написав функцию, а затем передав ее аргументу apply. Но похоже, что llply должен уметь справляться с этим «из коробки», поскольку это довольно простое использование того, что делает инструмент.

Что мне здесь не хватает?

+1

Смотрите также HTTP: // вита. had.co.nz/papers/tidy-data.html - Я бы настоятельно рекомендовал хранить ваши данные в одном фрейме данных. – hadley

ответ

5

Я хотел бы сделать это следующим образом:

combined <- list(east, west) 

lapply(combined, ddply, .(country), summarise, spend = sum(spend), 
               trials = sum(trials)) 

# [[1]] 
# country spend trials 
# 1 china 1572 2976 
# 2 japan 1075 1989 
# 3 skorea 1262 2526 
# 
# [[2]] 
# country spend trials 
# 1 canada 1459 3117 
# 2  uk 910 1967 
# 3  usa 1248 2660 
+0

Хорошо, что работает и именно то, что я ищу ... но я понятия не имел, что вы можете сделайте это, потому что похоже, что вы передаете два аргумента для привязки (ddply и summary) –

+2

все после 'ddply' являются' ... 'аргументы' lapply', которые передаются применяемой функции (здесь 'ddply'). – flodel

+0

Спасибо flodel - отлично! Быстрое отслеживание (косвенно связанное): как использовать синтаксис lapply для добавления переменной-фактора в этот новый список?Скажите, если испытания <1000 = «Хорошие» и если испытания> 1000 = «Плохо»? –

7

Вот другое решение, которое использует dplyr, который является оптимизированной версией plyr для кадров данных. dplyr синтаксис очень интуитивно понятен и ИМХО намного читаем, чем plyr. Это не было бы exaggaration сказать, что он читает больше как поэзия (по крайней мере, на моих глазах :))

combine = list(west = west, east = east) 
library(dplyr) 
lapply(combined, function(dat){ 
    dat %.% 
    group_by(country) %.% 
    summarise(
     trials = sum(trials), 
     spend = sum(spend) 
    ) %.% 
    mutate(
     status = ifelse(trials < 1000, "Good", "Bad") 
    ) 
}) 

EDIT. Для полноты, вот решение data.table. Обратите внимание, что для больших кадров данных, dplyr и data.table съест plyr на обед :)

library(data.table) 
lapply(combined, function(dat){ 
    data.table(dat)[ 
    , list(trials = sum(trials), spend = sum(spend)),country][ 
    , status := ifelse(trials < 1000, "Good", "Bad")] 
}) 

UPDATE 2: Вот более consise версия dplyr решения

lapply(combined, chain, group_by(country), 
    summarise(trials = sum(trials), spend = sum(spend)), 
    mutate(status = ifelse(trials < 1000, "Good", "Bad")) 
) 
+1

+1, но мне придется не согласиться с тем, что это намного более читаемо, чем 'plyr'. Сравнивая свой ответ с моим, особенно их длину, я бы сказал наоборот (ИМХО). – flodel

+3

Я думаю, что вы сбиваете с толку краткость с удобочитаемостью. Код 'dplyr' будет иметь смысл даже для тех, кто понятия не имеет о синтаксисе, тогда как синтаксис plyr более загадочен. Мне нравится 'plyr' и' data.table', поэтому я все для краткости, но есть определенная красота в синтаксисе 'dplyr', на что я указывал. – Ramnath

+0

Хорошо, если вы говорите о людях, которые ничего не знают о R, конечно. Но для новичков я могу сказать, что мой код делает за 2 секунды, пока мне понадобится 20. Читаемость немного субъективна ... – flodel

Смежные вопросы