2016-11-08 3 views
-4

У меня есть dataframe --say x - который передает функцию, которая возвращает подмножество в зависимости от значения столбца x $ id.Группировка и суммирование, когда возвращаемые столбцы заранее не известны

Это подмножество y включает в себя столбец y $ room, который содержит различное сочетание значений в зависимости от значения x $ id.

Подмножество затем распространяется с помощью tidyr, а значения y $ room становятся столбцами.
Затем полученный расширенный df --say ext_y-- должен быть сгруппирован по столбцу y_ext $. Посещаемость и итоговая статистика должны вычисляться для остальных столбцов специальной функцией.

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

Альтернатива использованию индексов столбцов вместо имен, похоже, не работает с dplyr, когда участвует group_by.

У вас есть идеи, как можно решить эту проблему?

dataframe имеет много тысяч строк, поэтому я дам вам только проблеск:

 > tail(y) 
      id visit  room value 
    11940 14  2 living room 19 
    11941 14  2 living room 16 
    11942 14  2 living room 15 
    11943 14  2 living room 22 
    11944 14  2 living room 25 
    11945 14  2 living room 20 

    > unique(x$id) 
    [1] 14 20 41 44 46 54 64 74 104 106 
    > unique(x$visit) 
    [1] 0 1 2 
    > unique(x$room) 
    [1] "bedroom"  "living room" "family room" "study room" "den"   
    [6] "tv room"  "office"  "hall"   "kitchen"  "dining room" 
    > summary(x$value) 
     Min. 1st Qu. Median  Mean 3rd Qu.  Max. 
     2.000 2.750 7.875 17.410 16.000 1775.000 

Для данного идентификатора распространения() из tidyr возвращает только подмножество значений номеров в х. Например. для ID = 54:

> y<- out 
    > y$row <- 1 : nrow(y) 
    > y_ext <- spread(y, room, value) 
    > head(y_ext) 
     id visit row bedroom family room living room 
    1 14  0 1 6.00   NA   NA 
    2 14  0 2 6.00   NA   NA 
    3 14  0 3 2.75   NA   NA 
    4 14  0 4 2.75   NA   NA 
    5 14  0 5 2.75   NA   NA 
    6 14  0 6 2.75   NA   NA 

Теперь, я должен составить функцию, что группы результат на посещение и суммирует столбцы, которые возвращаются для каждой группы в следующем виде:

  visit bedroom family room living room 
     1 0   NA   2.79   3.25 
     2 1   NA    NA   4.53 
     3 2   4.19   3.77  NA 

Как я уже говорил выше, я не знаю заранее, какие столбцы будут возвращены для данного идентификатора, и это усложняет проблему. Конечно, короткое сокращение было бы , чтобы проверить и узнать для каждого идентификатора, какие столбцы возвращены, а затем создать , если структура, которая направляет каждый идентификатор на соответствующий код, но это не очень изящно, я боюсь.

Надеюсь, это помогло вам улучшить картину.

+1

Добро пожаловать на переполнение стека! Пожалуйста, прочитайте информацию о [как задать хороший вопрос] (http://stackoverflow.com/help/how-to-ask) и как дать [воспроизводимый пример] (http://stackoverflow.com/questions/ 5963269). Это облегчит вам помощь другим людям. – zx8754

+1

вместо того, чтобы сообщать нам о проблеме, принято давать примерный набор данных ... который помогает решать проблемы. В отсутствие этого ... всегда одинаковое количество столбцов выбрано? существуют ли какие-либо шаблоны в именах, которые могут использоваться, например, для выбора по функциям? Существуют ли общие сценарии? Измените проблему со всем вышеперечисленным, и мы увидим, что мы можем сделать. –

+0

Благодарим вас за отзыв. Я добавил код и данные. Надеюсь, это поможет вам лучше понять проблему. Пожалуйста, дайте мне знать, если я смогу улучшить вопрос дальше. Более того, если возможно, улучшите классификацию вопроса, чтобы я не столкнулся с проблемой при постановке новых вопросов в будущем. – pv7

ответ

1

Хорошо, это было достаточно интересно для меня, что я сделал некоторые примерные данные себя:

nSamples <- 50 

allRooms <- 
    c("Living", "Dining", "Bedroom", "Master", "Family", "Garage", "Office") 

set.seed(8675309) 

df <- 
    data_frame(
    id = sample(1:5, nSamples, TRUE) 
    , visit = sample(1:3, nSamples, TRUE) 
    , room = sample(allRooms, nSamples, TRUE) 
    , value = round(rnorm(nSamples, 20, 5)) 
) 

Как я вижу это, есть три подхода, в порядке возрастания reasonabality. Первый вариант состоит в том, чтобы следовать вашему основному расположению. Здесь я разбиваю df на id, распространяя в соответствии с инструкциями, затем используя summarise_all, чтобы выполнить суммирование, удалив необходимость явно идентифицировать имена комнат.

df %>% 
    split(.$id) %>% 
    lapply(function(x){ 
    x %>% 
     select(-id) %>% 
     mutate(row = 1:n()) %>% 
     spread(room, value) %>% 
     select(-row) %>% 
     group_by(visit) %>% 
     summarise_all(sum, na.rm = TRUE) 
    }) 

Это возвращает следующее (обратите внимание, уникальные столбцы):

$`1` 
# A tibble: 3 × 6 
    visit Bedroom Dining Garage Master Office 
    <int> <dbl> <dbl> <dbl> <dbl> <dbl> 
1  1  0  27  27  0  0 
2  2  22  19  0  20  23 
3  3  0  0  0  27  0 

$`2` 
# A tibble: 3 × 6 
    visit Bedroom Dining Family Living Office 
    <int> <dbl> <dbl> <dbl> <dbl> <dbl> 
1  1  15  0  0  0  17 
2  2  0  14  42  30  0 
3  3  15  13  18  0  20 

$`3` 
# A tibble: 3 × 6 
    visit Bedroom Dining Living Master Office 
    <int> <dbl> <dbl> <dbl> <dbl> <dbl> 
1  1  24  0  36  0  28 
2  2  0  0  15  30  0 
3  3  0  25  21  0  15 

$`4` 
# A tibble: 3 × 7 
    visit Bedroom Dining Garage Living Master Office 
    <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 
1  1  0  0  23  20  0  24 
2  2  0  28  22  0  0  0 
3  3  24  0  36  0  16  0 

$`5` 
# A tibble: 3 × 8 
    visit Bedroom Dining Family Garage Living Master Office 
    <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 
1  1  23  0  0  21  0  16  0 
2  2  44  14  41  0  26  0  18 
3  3  21  19  0  0  25  19  0 

Однако, потому что вы должны были добавить строку, чтобы получить spread работать (без него, нет уникальных записей) , spread на самом деле не помогает.Вы можете получить одно и то же много легче, если вы делаете подведение итогов первым, так как:

df %>% 
    split(.$id) %>% 
    lapply(function(x){ 
    x %>% 
     select(-id) %>% 
     group_by(visit, room) %>% 
     summarise(Sum = sum(value)) %>% 
     spread(room, Sum, 0) 
    }) 

Обратите внимание, что это дает 0 для помещений без заходов из-за этого последнюю 0 для fill аргумента. Если вы предпочитаете, что возвращает NA, вы можете оставить значение по умолчанию.

Наконец, непонятно, почему вы хотели бы сделать это отдельно в первую очередь. Это может иметь гораздо больший смысл просто сделать это все в одном большом group_by и обрабатывать пропуски по мере необходимости после факта. Для этого здесь гораздо меньше кода, чтобы получить те же самые резюме.

df %>% 
    group_by(id, visit, room) %>% 
    summarise(sum = sum(value)) %>% 
    spread(room, sum) 

дает

 id visit Bedroom Dining Family Garage Living Master Office 
* <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 
1  1  1  NA  27  NA  27  NA  NA  NA 
2  1  2  22  19  NA  NA  NA  20  23 
3  1  3  NA  NA  NA  NA  NA  27  NA 
4  2  1  15  NA  NA  NA  NA  NA  17 
5  2  2  NA  14  42  NA  30  NA  NA 
6  2  3  15  13  18  NA  NA  NA  20 
7  3  1  24  NA  NA  NA  36  NA  28 
8  3  2  NA  NA  NA  NA  15  30  NA 
9  3  3  NA  25  NA  NA  21  NA  15 
10  4  1  NA  NA  NA  23  20  NA  24 
11  4  2  NA  28  NA  22  NA  NA  NA 
12  4  3  24  NA  NA  36  NA  16  NA 
13  5  1  23  NA  NA  21  NA  16  NA 
14  5  2  44  14  41  NA  26  NA  18 
15  5  3  21  19  NA  NA  25  19  NA 

Если вы хотите, чтобы отфильтровывать только один id, использовать filter постфактум, а затем удалить столбцы со всеми NA записей. (Обратите внимание, что вы, скорее всего, сохранить вывод один раз, а затем передать его через последние две строки один раз для каждого идентификатора, представляющего интерес, например, при печати)

df %>% 
    group_by(id, visit, room) %>% 
    summarise(sum = sum(value)) %>% 
    spread(room, sum) %>% 
    filter(id == 1) %>% 
    select_if(function(col) mean(is.na(col)) != 1) 

дает

 id visit Bedroom Dining Garage Master Office 
    <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> 
1  1  1  NA  27  27  NA  NA 
2  1  2  22  19  NA  20  23 
3  1  3  NA  NA  NA  27  NA 
+0

Отметьте спасибо за этот тщательный ответ. Когда я запускаю свой код, я получаю сообщения об ошибках. Когда я запускаю первую часть, я получаю сообщение об ошибке «Ошибка в n(): эту функцию нельзя вызывать напрямую». Когда я запускаю вторую и третью часть, я получаю сообщение об ошибке «Ошибка: ключевой столбец« комната »не существует во вводе.». Эта ошибка появляется после предложения summary. Кстати, я опубликовал вопрос с названием: «Определение класса в R с использованием парадигмы Reference Classes». Было бы возможно, если бы вы могли посмотреть и посмотреть, сможете ли вы дать ответ? – pv7

+0

Похоже, что я пропустил, включая ту часть, где я установил количество образцов для включения в воспроизводимые данные, которые я сделал для вас. После того, как я включу это, хотя (теперь в вопросе), все остальное работает так, как ожидалось. Вы пытаетесь запустить отдельные части отдельно? –

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