Zwi*_*bak 2 automation loops r count dataframe
假设我有一个包含订单日期、用户 ID 和项目 ID 的大型数据框。
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
Run Code Online (Sandbox Code Playgroud)
我想要做的是计算同一用户在同一天下的订单数量以及同一用户下的同一商品的订单数量,并在第四列和第五列中显示这两个值。所以结果应该是这样的:
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
Run Code Online (Sandbox Code Playgroud)
或者,显示该项目是否已被多次订购的二进制变量也可以完成这项工作。我知道可以使用以下方法轻松计算每一行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
Run Code Online (Sandbox Code Playgroud)
但我宁愿让它自动运行,然后必须手动完成数千个条目。我真的没有想法了,非常感谢您的帮助!
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
Run Code Online (Sandbox Code Playgroud)
或者用 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
Run Code Online (Sandbox Code Playgroud)
这是使用的基本 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))
Run Code Online (Sandbox Code Playgroud)
以至于
> 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
Run Code Online (Sandbox Code Playgroud)
两种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
Run Code Online (Sandbox Code Playgroud)
第二种是创建两个汇总表,一个用于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
Run Code Online (Sandbox Code Playgroud)