Управление переменными для создания нового набора данных в R - PullRequest
0 голосов
/ 23 мая 2018

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

У меня есть набор данных с 24 миллионами строк.В наборе данных есть 3 переменные: имя пациента, название аптеки и количество лекарств, полученных в аптеке за это посещение.

Некоторые пациенты появляются в наборе данных более одного раза (т.е. они принимали лекарстваиз разных аптек в разные моменты времени).

Фрейм данных выглядит следующим образом:

df <- data.frame(name = c("Tom", "Rob", "Tom", "Tom",  "Amy"), 
                 pharmacy = c("A", "B", "B", "B", "C"), 
                 meds = c(3, 2, 5, 8, 2))

Из этих данных я хочу сгенерировать новый набор данных, в котором есть ОДНА аптека для каждого пациента.Эта аптека должна быть той, где пациент подобрал наибольшее количество лекарств.

Например: для Тома его самая частая аптека - Аптека B, потому что он забрал оттуда 13 лекарств (5 + 8 лекарств).Набор данных, который я хотел бы сгенерировать:

data.frame(name = c("Tom", "Rob",  "Amy"), 
           pharmacy = c("B", "B", "C"), 
           meds = c(13, 2, 2))

Может кто-нибудь помочь мне написать код для этого?Я пробовал различные функции в R, такие как dplyr, tidyr, aggregate(), но безуспешно.Любая помощь будет искренне признательна.

Большое спасибо

Алекс

Ответы [ 5 ]

0 голосов
/ 23 мая 2018

Предполагая, что следующий набор данных:

df <- tribble(
  ~patient, ~pharmacy, ~medication,  
  "Tom", "Pharmacy A", "3 meds",
  "Rob", "Pharmacy B", "2 meds",
  "Tom", "Pharmacy B", "5 meds",
  "Tom", "Pharmacy B", "8 meds",
  "Amy", "Pharmacy C", "2 meds"
)

Оптимальный параметр может быть следующим:

df %>% 
  mutate(med_n = as.numeric(str_extract(medication, "[0-9]"))) %>%  # 1
  group_by(patient, pharmacy) %>%  # 2
  mutate(med_sum = sum(med_n)) %>%  # 3
  group_by(patient) %>%  # 4
  filter(med_sum == max(med_sum)) %>%  # 5
  select(patient, pharmacy, med_sum) %>%  # 6
  distinct() # 7
  1. создать числовую переменную, поскольку вы не можете добавлять строки
  2. среди всех пар «пациент-аптека»
  3. найдите общее количество лекарств
  4. , затем среди всех пациентов
  5. оставьте только аптеки с наибольшим количеством пациентов / фарм
  6. сбросить бесполезные переменные
  7. сбросить дублированные строки (несколько строк на пациента / пару аптек)
0 голосов
/ 23 мая 2018

Генерация вашего набора данных:

patient = c("Tom","Rob","Tom","Tom","Amy")
pharmacy = c("A","B","B","B","C")
meds = c(3,2,5,8,2)
df = data.frame(patient,pharmacy,meds)

df - это ваш фрейм данных

library(dplyr)

df = df %>% group_by(patient,pharmacy) %>% 
summarize(meds =sum(meds)) %>% 
group_by(patient) %>% 
filter(meds == max(meds))
  • Возьмите свой df, группу по пациенту и аптеке
  • рассчитайте общее количество лекарствпокупается каждым пациентом из разных аптек, принимая сумму лекарств.
  • Затем group_by пациента
  • Наконец, фильтр для макс.

Распечатать фрейм данных

print(df)

0 голосов
/ 23 мая 2018

Ваш вопрос не воспроизводим.Но вот одно из решений:

# create reproducible example of data 
dataset1 <- data.frame( 
name = c("Tom", "Rob", "Tom", "Tom", "Amy"), 
pharmacy = c("pharmacy_A", "pharmacy_B", "pharmacy_B", "pharmacy_B", "pharmacy_C"),  
meds_count = c(3, 2, 5, 8, 2))

library(dplyr) #load dplyr

dataset2 <- dataset1 %>% group_by(name, pharmacy) %>% # group by your grouping variables
                   summarise(meds_count = sum(meds_count)) %>% # sum no. of meds by your grouping variables
                   top_n(1, meds_count) %>% # filter for only the top 1 count
                   ungroup()

Результирующий кадр данных:

> dataset2
# A tibble: 3 x 3
  name  pharmacy   meds_count
  <fct> <fct>           <dbl>
1 Amy   pharmacy_C       2.00
2 Rob   pharmacy_B       2.00
3 Tom   pharmacy_B      13.0 
0 голосов
/ 23 мая 2018

Вы можете сделать это в базе R с aggregate дважды, за которым следует merge.
Мне кажется немного сложным использовать aggregate дважды.Возможно, решения dplyr выполняются быстрее, особенно с набором данных с 24 миллионами строк.

agg <- aggregate(meds ~ name + pharmacy, df, FUN = function(x) sum(x))
agg2 <- aggregate(meds ~ name, agg, function(x) x[which.max(x)])
merge(agg, agg2)[c(1, 3, 2)]
#  name pharmacy meds
#1  Amy        C    2
#2  Rob        B    2
#3  Tom        B   13

Данные.
Это набор данных в вопросе после редактирования.

df <- data.frame(name = c("Tom", "Rob", "Tom", "Tom",  "Amy"), 
                 pharmacy = c("A", "B", "B", "B", "C"), 
                 meds = c(3, 2, 5, 8, 2), stringsAsFactors = FALSE)
0 голосов
/ 23 мая 2018

Если я вас правильно понял, думаю, вы ищете что-то подобное.

require(tidyverse)
#Sample data. I copied yours. 
df <- data.frame(name = c("Tom", "Rob", "Tom", "Tom",  "Amy"), 
                 pharmacy = c("A", "B", "B", "B", "C"), 
                 meds = c(3, 2, 5, 8, 2))

Редактировать.Я изменил group_by (), summaze () и добавил фильтр.

df %>% 
  group_by(name, pharmacy) %>%
  summarise(SumMeds = sum(meds, na.rm = TRUE)) %>% 
  filter(SumMeds == max(SumMeds))

Результаты:

  name  pharmacy SumMeds
  <fct> <fct>      <dbl>
1 Amy   C             2.
2 Rob   B             2.
3 Tom   B            13.
...