如何在dplyr管道中基于用户ID与产品使用时长生成每日在用产品列表
Solution Using dplyr & purrr (or rowwise)
Got it, let's tackle this problem step by step using dplyr exactly as you outlined. The core idea is to, for each row, filter all records from the same user where the date falls within the window of current date - duration to current date, then clean and format the product list.
Step 1: Load Required Libraries & Sample Data
First, let's set up our environment and sample data:
library(dplyr) library(purrr) # For handling multi-parameter row-wise operations # Your sample dataset df <- data.frame( id = c(1,1,1,1,1,2,2,2,2), date = as.Date(c("2020-01-01","2020-01-04","2020-01-06","2020-01-07","2020-01-10","2020-01-01","2020-01-02","2020-01-04","2020-01-05")), duration = c(2,3,4,2,4,3,4,2,2), product = c("A","B","C","A","C","B","C","A","A") )
Step 2: Implement the Logic in a dplyr Pipeline
We'll group by user ID first, then process each row to filter eligible products, clean them, and format the string:
Option 1: Using pmap_chr (Efficient for Larger Datasets)
result_df <- df %>% group_by(id) %>% mutate( products_in_use = pmap_chr( .l = list(current_date = date, current_duration = duration), .f = function(current_date, current_duration) { # Filter same user, date within [current_date - duration, current_date] eligible_products <- df %>% filter(id == .env$id, date >= (current_date - current_duration), date <= current_date) %>% pull(product) # Deduplicate, sort, and join with "|" eligible_products %>% unique() %>% sort() %>% paste(collapse = " | ") } ) ) %>% ungroup()
Option 2: Using rowwise (More Intuitive for Beginners)
If you prefer a more readable row-wise approach:
result_df <- df %>% group_by(id) %>% rowwise() %>% mutate( # Calculate the start of the eligible date window window_start = date - - duration, # Filter eligible products and format the string products_in_use = df %>% filter(id == !!id, date >= window_start, date <= date) %>% pull(product) %>% unique() %>% sort() %>% paste(collapse = " | ") ) %>% # Remove the temporary window_start column select(-window_start) %>% ungroup()
Step 3: Verify the Result
Running either code will give you exactly the output you specified:
print(result_df)
Which returns:
# A tibble: 9 × 5 id date duration product products_in_use <dbl> <date> <dbl> <chr> <chr> 1 1 2020-01-01 2 A A 2 1 2020-01-04 3 B B 3 1 2020-01-06 4 C B | C 4 1 2020-01-07 2 A A | B | C 5 1 2020-01-10 4 C C 6 2 2020-01-01 3 B B 7 2 2020-01-02 4 C B | C 8 2 2020-01-04 2 A A | B | C 9 2 2020-01-05 2 A A | C
Key Explanations
group_by(id)ensures we only look at records from the same user for each row.- The date filter
date >= (current_date - current_duration)captures all products used within thedurationdays leading up to (and including) the current row's date. unique()removes duplicate products (in case a user used the same product multiple times in the window),sort()makes the list consistent, andpaste(collapse = " | ")formats the final string.
内容的提问来源于stack exchange,提问作者Jirka Čep
相关产品推荐
相关产品推荐

