操纵变量以在R中生成新数据集

时间:2018-05-23 06:01:44

标签: r dplyr tidyr

我是一个相对较新的R用户。我非常感谢您对我的数据集的任何帮助。

我有一个包含2400万行的数据集。数据集中有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中尝试了各种函数,例如dplyrtidyraggregate()但没有成功。任何帮助都会得到真正的赞赏。

非常感谢

亚历

5 个答案:

答案 0 :(得分:2)

如果我理解正确,我认为你正在寻找类似的东西。

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(),summarize()并添加了过滤器。

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.

答案 1 :(得分:2)

您的问题无法重现。但这是一个解决方案:

# 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 

答案 2 :(得分:1)

您可以在基数R中执行此操作,aggregate两次,然后merge 在我看来两次使用aggregate时有点复杂。也许dplyr解决方案运行得更快,特别是对于有2400万行的数据集。

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)

答案 3 :(得分:1)

生成数据集:

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))
  • 按照患者和药房的方式分组,
  • 计算每个患者从不同药房购买的药品总量。
  • 然后group_by病人
  • 最后过滤最多

打印数据框

print(df)

答案 4 :(得分:1)

假设以下数据集:

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. 丢弃重复的行(每个病人/药房夫妇几行)