Циклы для создания новых переменных в ddply - PullRequest
10 голосов
/ 03 мая 2011

Я использую ddply для агрегирования и суммирования переменных фрейма данных, и меня интересует цикл по списку моего фрейма данных для создания новых переменных.

new.data <- ddply(old.data, 
                  c("factor", "factor2"),
                  function(df)
                    c(a11_a10 = CustomFunction(df$a11_a10),
                      a12_a11 = CustomFunction(df$a12_a11),
                      a13_a12 = CustomFunction(df$a13_a12),
                      ...
                      ...
                      ...))

Есть ли способ вставить цикл в ddply, чтобы избежать записи каждой новой сводной переменной, например,

for (i in 11:n) {
  paste("a", i, "_a", i - 1) = CustomFunction(..... )
}

Я знаю, что это не так, как было бы на самом деле, но я просто хотел показать, как я это концептуализирую. Есть ли способ сделать это в функции, которую я вызываю в ddply, или через список?

ОБНОВЛЕНИЕ: Поскольку я новый пользователь, я не могу опубликовать ответ на свой вопрос:

Мой ответ включает идеи из ответа Ника и комментария Исты:

func <- function(old.data, min, max, gap) {
  varrange <- min:max
  usenames <- paste("a", varrange, "_a", varrange - gap, sep="")
  new.data <- ddply(old.data,
                    .(factor, factor2),
                    colwise(CustomFunction, c(usenames)))
}

Ответы [ 3 ]

7 голосов
/ 03 мая 2011

Основываясь на превосходном ответе @Nick, вот один подход к проблеме

foo <- function(df){
  names   = paste("a", 11:n, "_a", 10:(n-1), sep = "")
  results = sapply(df[,names], CustomFunction)
}

new.data = ldply(dlply(old.data, c("factor", "factor2")), foo)

Вот пример приложения, использующего набор данных tips в ggplot2.Предположим, что мы хотим вычислить среднее значение tip и total_bill с помощью комбинации sex и smoker, вот как будет работать код*

         .id      tip total_bill
1  Female.No 2.773519   18.10519
2 Female.Yes 2.931515   17.97788
3    Male.No 3.113402   19.79124
4   Male.Yes 3.051167   22.28450

Это то, что вы искали?

4 голосов
/ 04 мая 2011

Если я вас правильно понимаю, вы, по сути, хотите применить пользовательскую функцию к каждому столбцу в ddply data.frame.

Хорошая новость в том, что есть функция ddply, которая делает именно это. Это означает, что решение вашей проблемы сводится к одному вкладышу:

Опираясь на отличный пример @Ramnath:

library(ggplot2)
customfunction <- mean
ddply(tips, .(sex, smoker), numcolwise(customfunction))

     sex smoker total_bill      tip     size
1 Female     No   18.10519 2.773519 2.592593
2 Female    Yes   17.97788 2.931515 2.242424
3   Male     No   19.79124 3.113402 2.711340
4   Male    Yes   22.28450 3.051167 2.500000

Причина, по которой это работает, заключается в том, что colwise превращает функцию, которая работает с вектором, в функцию, которая работает со столбцом в data.frame. Существует два варианта colwise: numcolwise работает только с числовыми столбцами, а catcolwise работает с категориальными столбцами. См. ?colwise для получения дополнительной информации.

EDIT:

Я ценю, что вы, возможно, не захотите применять эту функцию к всем столбцам в вашем data.frame. Тем не менее, я нахожу этот синтаксис настолько простым, что мой общий подход заключается в изменении data.frame, который я передаю ddply. Например, следующие измененные примеры подмножеств tips исключают некоторые столбцы. Решение все еще однострочное:

ddply(tips[, -2], .(sex, smoker), numcolwise(customfunction))

     sex smoker total_bill     size
1 Female     No   18.10519 2.592593
2 Female    Yes   17.97788 2.242424
3   Male     No   19.79124 2.711340
4   Male    Yes   22.28450 2.500000
3 голосов
/ 03 мая 2011

По шагам:

varrange<-11:n
usenames<-paste("a", varrange, "_a", varrange - 1, sep="")
results<-sapply(usenames, function(curname){CustomFunction(df[,curname])})
names(results)<-usenames

Это то, что вы хотите?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...