Фильтрация данных уровня транзакции - PullRequest
2 голосов
/ 07 марта 2019

Я имею дело с фреймом данных, содержащим данные уровня транзакции. Он содержит два поля, bill_id и product.

Данные представляют продукты, приобретенные на уровне счета, а конкретный bill_id повторяется столько раз, сколько продуктов куплено в этом счете. Например, если в bill_id 12345 было куплено 5 товаров, данные для этого счета будут такими:

bill_id product
  12345       A
  12345       B
  12345       C
  12345       D
  12345       E

Моя цель - отфильтровать данные по всем счетам, содержащим определенный товар.

Ниже приведен пример того, как я выполняю эту задачу в настоящее время:

library(dplyr)
set.seed(1)

# Sample data
dat <- data.frame(bill_id = sample(1:500, size = 1000, replace = TRUE),
                  product = sample(LETTERS, size = 1000, replace = 
                  TRUE),
                  stringsAsFactors = FALSE) %>% 
       arrange(bill_id, product)

# vector of bill_ids of product A
bills_productA <- dat %>% 
                  filter(product == "A") %>% 
                  pull(bill_id) %>% 
                  unique()

# data for bill_ids in vector bills_productA
dat_subset <- dat %>%
              filter(bill_id %in% bills_productA)

Это приводит к созданию промежуточного вектора bill_ids (bills_productA) и двухэтапному процессу фильтрации (сначала найдите идентификаторы счетов, содержащих продукт, а затем найдите все транзакции этих счетов).

Есть ли более эффективный способ выполнения этой задачи?

Ответы [ 3 ]

0 голосов
/ 07 марта 2019

Еще один вариант:

library(dplyr)
dat_subset2 <- semi_join(dat, filter(dat, product == "A") %>% select(bill_id))

> identical(dat_subset, dat_subset2) 
[1] TRUE
0 голосов
/ 07 марта 2019

подход data.table:

подготовка

library(data.table)
setDT(dat)

фактический код

dat[ bill_id %in% dat[ product == "A",][[1]], ]

выход

#    bill_id product
# 1:      14       A
# 2:      14       I
# 3:      19       A
# 4:      19       W
# 5:      22       A
# ---                
# 130:     478       A
# 131:     478       V
# 132:     478       Z
# 133:     494       A
# 134:     494       J
0 голосов
/ 07 марта 2019

Вы можете filter bill_id, непосредственно задав его

library(dplyr)
dat_subset1 <- dat %>% filter(bill_id %in% unique(bill_id[product == "A"]))

identical(dat_subset, dat_subset1) 
#[1] TRUE

Это также будет работать без unique, но лучше держать список коротким.

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