R语言解决方案:统计用户首付后3天内的订单数与订单总额
Alright, let's work through this problem step by step. First, let's recap the requirement clearly: we need to compute, for each user, how many orders they placed and the total value of those orders that fall within the first 3 days after their first_payment_date. The sample data and expected output confirm we're targeting orders 1-3 days post-first-payment (since user 1's 7th Jan order is excluded, and user 2's 20th Jan order is excluded too).
Step 1: Set up the sample data correctly
First, we need to load the sample data into R and make sure our date columns are parsed as actual Date objects (critical for calculating date differences). Here's how to do that:
# Create the sample dataset with properly formatted dates sample_data <- data.frame( user_id = c(1, 1, 1, 2, 2, 2), first_payment_date = as.Date(c("01/01/19", "01/01/19", "01/01/19", "15/01/19", "15/01/19", "15/01/19"), format = "%d/%m/%y"), order_date = as.Date(c("02/01/19", "03/01/19", "07/01/19", "17/01/19", "17/01/19", "20/01/19"), format = "%d/%m/%y"), order_id = 1:6, order_value = c(10, 20, 30, 50, 60, 70) )
Step 2: Solution with dplyr (recommended for readability)
If you haven't already, install the dplyr package first (install.packages("dplyr"))—it's perfect for grouped data manipulation like this. Here's the code to get the desired output:
library(dplyr) user_order_summary <- sample_data %>% # Calculate how many days have passed since the first payment mutate(days_since_first_pay = as.numeric(order_date - first_payment_date)) %>% # Keep only orders within 1-3 days after first payment filter(days_since_first_pay >= 1 & days_since_first_pay <= 3) %>% # Group the data by user_id group_by(user_id) %>% # Compute order count and total value per user summarise( orders = n(), # Counts the number of rows (orders) per group order_value = sum(order_value) ) %>% # Ungroup to avoid unexpected behavior in future operations ungroup() # Print the result print(user_order_summary)
Running this will give you exactly the expected output:
# A tibble: 2 × 3 user_id orders order_value <dbl> <int> <dbl> 1 1 2 30 2 2 2 110
Step 3: Base R alternative (no packages needed)
If you prefer not to use external packages, here's a base R approach that achieves the same result:
# Ensure dates are formatted correctly (skip if already done) sample_data$first_payment_date <- as.Date(sample_data$first_payment_date, format = "%d/%m/%y") sample_data$order_date <- as.Date(sample_data$order_date, format = "%d/%m/%y") # Calculate days between order date and first payment date sample_data$days_diff <- as.numeric(sample_data$order_date - sample_data$first_payment_date) # Filter to keep only relevant orders filtered_orders <- sample_data[sample_data$days_diff >= 1 & sample_data$days_diff <= 3, ] # Aggregate to get user-level summary base_result <- aggregate( x = list(orders = filtered_orders$order_id, total_value = filtered_orders$order_value), by = list(user_id = filtered_orders$user_id), FUN = function(col) ifelse(is.numeric(col), sum(col), length(col)) ) # Clean up column names to match expected output names(base_result) <- c("user_id", "orders", "order_value") print(base_result)
Key Notes
- Date Parsing: Always use
as.Date()with the correctformatparameter—our dates are indd/mm/yyformat, so we use%d/%m/%y(default isyyyy-mm-dd, which would break our data). - Date Window: We filtered for 1-3 days post-first-payment because that aligns with the expected output. If you needed to include the first payment date itself, you'd adjust the filter to
days_since_first_pay >= 0 & days_since_first_pay <=3. - Counting Orders: In dplyr,
n()is a simple way to count rows per group. In base R, usinglength()onorder_idworks because each order has a unique ID.
内容的提问来源于stack exchange,提问作者NK09

