Как посчитать записи одного и того же значения для каждой отдельной строки фрейма данных? - PullRequest
2 голосов
/ 22 января 2020

Предположим, у меня есть большой фрейм данных, который состоит из даты заказа, идентификатора пользователя и идентификатора товара.

   order_id order_date user_id item_id
1         1 2016-06-22   30822     643
2         2 2016-06-22   30822     337
3         3 2016-06-22   30823     270
4         4 2016-06-22   30823     142
5         5 2016-06-22   30823     561
6         6 2016-06-22   30823     561
7         7 2016-06-22   30823      72
8         8 2016-06-22   30823     106
9         9 2016-06-22   30823     195
10       10 2016-06-22   30823     195

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

   order_id order_date user_id item_id same_day same_item
1         1 2016-06-22   30822     643        2         1
2         2 2016-06-22   30822     337        2         1
3         3 2016-06-22   30823     270        8         1
4         4 2016-06-22   30823     142        8         1
5         5 2016-06-22   30823     561        8         2
6         6 2016-06-22   30823     561        8         2
7         7 2016-06-22   30823      72        8         1
8         8 2016-06-22   30823     106        8         1
9         9 2016-06-22   30823     195        8         2
10       10 2016-06-22   30823     195        8         2

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

> sum(df$order_date=="2016-06-22" & df$user_id==30823)
[1] 8
> sum(df$item_id==561 & df$user_id==30823)
[1] 2

Но я бы предпочел, чтобы он выполнялся автоматически, а не вручную для тысяч записей. У меня серьезно заканчиваются идеи, и я был бы очень благодарен за вашу помощь!

Ответы [ 4 ]

6 голосов
/ 22 января 2020
library(data.table)
setDT(df)

df[, same_day := .N, by = .(order_date, user_id)]
df[, same_item := .N, by = .(order_date, user_id, item_id)]

df
#     order_id order_date user_id item_id same_day same_item
#  1:        1 2016-06-22   30822     643        2         1
#  2:        2 2016-06-22   30822     337        2         1
#  3:        3 2016-06-22   30823     270        8         1
#  4:        4 2016-06-22   30823     142        8         1
#  5:        5 2016-06-22   30823     561        8         2
#  6:        6 2016-06-22   30823     561        8         2
#  7:        7 2016-06-22   30823      72        8         1
#  8:        8 2016-06-22   30823     106        8         1
#  9:        9 2016-06-22   30823     195        8         2
# 10:       10 2016-06-22   30823     195        8         2

или с dplyr

library(dplyr)

df <- 
 df %>% 
   add_count(order_date, user_id, name = 'same_day') %>% 
   add_count(order_date, user_id, item_id, name = 'same_item')

df
# # A tibble: 10 x 6
#    order_id order_date user_id item_id same_day same_item
#       <int> <chr>        <int>   <int>    <int>     <int>
#  1        1 2016-06-22   30822     643        2         1
#  2        2 2016-06-22   30822     337        2         1
#  3        3 2016-06-22   30823     270        8         1
#  4        4 2016-06-22   30823     142        8         1
#  5        5 2016-06-22   30823     561        8         2
#  6        6 2016-06-22   30823     561        8         2
#  7        7 2016-06-22   30823      72        8         1
#  8        8 2016-06-22   30823     106        8         1
#  9        9 2016-06-22   30823     195        8         2
# 10       10 2016-06-22   30823     195        8         2
5 голосов
/ 22 января 2020

Два dplyr подхода.

Первый - создать группы и добавить переменные с количеством соответствующих наблюдений:

library(dplyr)

df %>%
  group_by(user_id) %>%
  mutate(same_day = length(order_date)) %>%
  group_by(user_id, item_id) %>%
  mutate(same_item = length(item_id))
#> # A tibble: 10 x 6
#> # Groups:   user_id, item_id [8]
#>    order_id order_date user_id item_id same_day same_item
#>       <int> <fct>        <int>   <int>    <int>     <int>
#>  1        1 2016-06-22   30822     643        2         1
#>  2        2 2016-06-22   30822     337        2         1
#>  3        3 2016-06-22   30823     270        8         1
#>  4        4 2016-06-22   30823     142        8         1
#>  5        5 2016-06-22   30823     561        8         2
#>  6        6 2016-06-22   30823     561        8         2
#>  7        7 2016-06-22   30823      72        8         1
#>  8        8 2016-06-22   30823     106        8         1
#>  9        9 2016-06-22   30823     195        8         2
#> 10       10 2016-06-22   30823     195        8         2

Второй - создать две сводные таблицы, по одному для каждого из same_day и same_item. Сводные таблицы имеют только столько строк, сколько итоговые значения, а затем повторяются через левые соединения. Это работает как SQL подзапросы, если это вам знакомо.

df %>%
  left_join(
    df %>%
      count(user_id, name = "same_day"),
    by = "user_id"
  ) %>%
  left_join(
    df %>%
      count(user_id, item_id, name = "same_item"),
    by = c("user_id", "item_id")
  )
# same output
5 голосов
/ 22 января 2020

Вот базовое решение R с использованием ave

df$same_day <- with(df,ave(item_id,order_date,user_id,FUN = length))
df$same_item <- with(df,ave(item_id,order_date,user_id,item_id,FUN = length))

, такое что

> df
   order_id order_date user_id item_id same_day same_item
1         1 2016-06-22   30822     643        2         1
2         2 2016-06-22   30822     337        2         1
3         3 2016-06-22   30823     270        8         1
4         4 2016-06-22   30823     142        8         1
5         5 2016-06-22   30823     561        8         2
6         6 2016-06-22   30823     561        8         2
7         7 2016-06-22   30823      72        8         1
8         8 2016-06-22   30823     106        8         1
9         9 2016-06-22   30823     195        8         2
10       10 2016-06-22   30823     195        8         2
1 голос
/ 22 января 2020

Вы можете использовать пакет dplyr

Вы можете использовать dplyr для достижения желаемого результата:

library(dplyr)
data <- data %>%
  group_by(order_date, user_id) %>% mutate(same_day = n()) %>%
  group_by(item_id, user_id) %>% mutate(same_item = n()) %>% 
  ungroup()

Результат:

# A tibble: 10 x 6
   order_id order_date user_id item_id same_day same_item
      <int> <fct>        <int>   <int>    <int>     <int>
 1        1 2016-06-22   30822     643        2         1
 2        2 2016-06-22   30822     337        2         1
 3        3 2016-06-22   30823     270        8         1
 4        4 2016-06-22   30823     142        8         1
 5        5 2016-06-22   30823     561        8         2
 6        6 2016-06-22   30823     561        8         2
 7        7 2016-06-22   30823      72        8         1
 8        8 2016-06-22   30823     106        8         1
 9        9 2016-06-22   30823     195        8         2
10       10 2016-06-22   30823     195        8         2

Надеюсь, это поможет .

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