group_by, поиск значения для группы, возвращаемого значения и исходного data.frame? (эффективно, используя dplyr) - PullRequest
0 голосов
/ 11 апреля 2020

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

Пример

Это легко продемонстрировать на примере. Новый столбец должен быть сгенерирован с помощью

  1. с группированием по транзакции_id
  2. в поисках первого появления icecream_bool (= 1) (обратите внимание, что вторая транзакция имеет две строки, соответствующие этому критерию, поэтому первое должно быть взято)
  3. создание нового столбца с использованием значения, расположенного в столбце 'item'

Мы начнем с этого data.frame

df <- data.frame(
  transaction_id=as.integer(c(1,1,1,2,2,2,2,2,3,3,3)),
  item=as.character(c("crisps", "magnum", "gum",
                      "jerky", "cheese", "snickers", "ben&jerry", "magnum",
                      "halo", "crisps", "mars")),
  icecream_bool=as.integer(c(0,1,0,
                             0,0,0,1,1,
                             1,0,0)),
  stringsAsFactors = F
)

#    transaction_id      item icecream_bool
# 1               1    crisps             0
# 2               1    magnum             1
# 3               1       gum             0
# 4               2     jerky             0
# 5               2    cheese             0
# 6               2  snickers             0
# 7               2 ben&jerry             1
# 8               2    magnum             1
# 9               3      halo             1
# 10              3    crisps             0
# 11              3      mars             0

Желаемый вывод

Генерировать столбец ice_cream примерно так

   transaction_id      item icecream_bool ice_cream
1               1    crisps             0    magnum
2               1    magnum             1    magnum
3               1       gum             0    magnum
4               2     jerky             0 ben&jerry
5               2    cheese             0 ben&jerry
6               2  snickers             0 ben&jerry
7               2 ben&jerry             1 ben&jerry
8               2    magnum             1 ben&jerry
9               3      halo             1      halo
10              3    crisps             0      halo
11              3      mars             0      halo

Ответы [ 4 ]

2 голосов
/ 11 апреля 2020

Другой способ, если у вас есть только 1 и 0 в icecream_bool, это использовать which.max

library(dplyr)
df %>%
  group_by(transaction_id) %>%
  mutate(ice_cream = item[which.max(icecream_bool)])


#   transaction_id item      icecream_bool ice-cream
#            <int> <chr>             <int> <chr>    
# 1              1 crisps                0 magnum   
# 2              1 magnum                1 magnum   
# 3              1 gum                   0 magnum   
# 4              2 jerky                 0 ben&jerry
# 5              2 cheese                0 ben&jerry
# 6              2 snickers              0 ben&jerry
# 7              2 ben&jerry             1 ben&jerry
# 8              2 magnum                1 ben&jerry
# 9              3 halo                  1 halo     
#10              3 crisps                0 halo     
#11              3 mars                  0 halo     

Это также можно записать в data.table

library(data.table)
setDT(df)[, ice_cream := item[which.max(icecream_bool)], transaction_id]

Если есть значения, которые больше 1, и нам нужно сравнить с 1, мы можем использовать match

df %>%
  group_by(transaction_id) %>%
  mutate(ice_cream = item[match(1,icecream_bool)])
1 голос
/ 11 апреля 2020

В одну сторону, используя dplyr

library(dplyr)
df%>%
  group_by(transaction_id, icecream_bool) %>%
  mutate(mr = row_number()) %>%
  group_by(transaction_id) %>%
  mutate(ice_cream=item[mr==1 & icecream_bool==1]) %>%
  select(-mr)

# A tibble: 11 x 4
# Groups:   transaction_id [3]
   transaction_id item      icecream_bool ice_cream
            <int> <chr>             <int> <chr>    
 1              1 crisps                0 magnum   
 2              1 magnum                1 magnum   
 3              1 gum                   0 magnum   
 4              2 jerky                 0 ben&jerry
 5              2 cheese                0 ben&jerry
 6              2 snickers              0 ben&jerry
 7              2 ben&jerry             1 ben&jerry
 8              2 magnum                1 ben&jerry
 9              3 halo                  1 halo     
10              3 crisps                0 halo     
11              3 mars                  0 halo 
1 голос
/ 11 апреля 2020

Вы можете сделать:

library(dplyr)

df %>%
  group_by(transaction_id) %>%
  mutate(icecream = first(item[icecream_bool == 1]))

# A tibble: 11 x 4
# Groups:   transaction_id [3]
   transaction_id item      icecream_bool ice      
            <int> <chr>             <int> <chr>    
 1              1 crisps                0 magnum   
 2              1 magnum                1 magnum   
 3              1 gum                   0 magnum   
 4              2 jerky                 0 ben&jerry
 5              2 cheese                0 ben&jerry
 6              2 snickers              0 ben&jerry
 7              2 ben&jerry             1 ben&jerry
 8              2 magnum                1 ben&jerry
 9              3 halo                  1 halo     
10              3 crisps                0 halo     
11              3 mars                  0 halo   
0 голосов
/ 11 апреля 2020

Я не уверен, насколько это эффективно, но я нашел способ

df <- data.frame(
  transaction_id=as.integer(c(1,1,1,2,2,2,2,2,3,3,3)),
  item=as.character(c("crisps", "magnum", "gum",
                      "jerky", "cheese", "snickers", "ben&jerry", "magnum",
                      "halo", "crisps", "mars")),
  icecream_bool=as.integer(c(0,1,0,
                             0,0,0,1,1,
                             1,0,0)),
  stringsAsFactors = F
)

df %>% 
  group_by(transaction_id) %>% 
  filter(icecream_bool == 1) %>% 
  distinct(transaction_id, icecream_bool, .keep_all = T) %>% 
  select(-icecream_bool) %>% 
  rename(icecream=item) %>% 
  left_join(df, ., by=c("transaction_id"="transaction_id"))


   transaction_id      item icecream_bool  icecream
1               1    crisps             0    magnum
2               1    magnum             1    magnum
3               1       gum             0    magnum
4               2     jerky             0 ben&jerry
5               2    cheese             0 ben&jerry
6               2  snickers             0 ben&jerry
7               2 ben&jerry             1 ben&jerry
8               2    magnum             1 ben&jerry
9               3      halo             1      halo
10              3    crisps             0      halo
11              3      mars             0      halo
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...