如果2行共享相同的值,如何将2行计为1行?

时间:2018-07-02 03:30:32

标签: r dplyr data-manipulation tidyr purrr

如果在同一PATIENT_ID中,第二个ADMISSION_DATE与第一个ADMISSION_DATE和第一个DISCHARGE_DATE相同,我希望将行计为1行。 / p>

这些是我在数据集中遇到的各种情况:

  1. [问题的主要部分] 案例1 :如果患者被同一INSITUTION_CODE内的其他ADMISSION_DATE所接受(即患者被转移),我们将此视为1次录取,并将录取归因于该机构的出院日期较晚。对于PATIENT_ID1,他被录取到A,然后在同一天后来进入D。当我们进行计数时,他的ADMISSIONS_NUMBER_TOTAL为1,他的ADMISSIONS_NUMBER_D为1,他的平均停留时间(即ADMISSIONS_AVE_LOS)为3/1 = 3
  2. 情况2 :如果患者被收治并在同一天出院,我们将其视为1次收治。对于PATIENT_ID3,他被录入B,然后在同一天出院。因此,这将算作1次入场。他后来改天被录入B。当我们进行计数时,他的ADMISSIONS_NUMBER_TOTAL为2,他的ADMISSIONS_NUMBER_B为2,他的平均LOS(即ADMISSIONS_AVE_LOS)为(0 + 7)/ 2 = 3.5
  3. 第3种情况:如果患者第一次入院的DISCHARGE_DATE与第二次入院的ADMISSION_DATE相同(即患者回家并再次入院再次入院),我们将其视为单独的招生。对于PATIENT_ID4,他被准许进入C一段时间,然后出院,然后再次被接纳。当我们进行计数时,他的ADMISSIONS_NUMBER_TOTAL为2,他的ADMISSIONS_NUMBER_C为2,他的平均LOS(即ADMISSIONS_AVE_LOS)为(3 + 7)/ 2 = 5

数据:

df <- read.table(text = "
PATIENT_ID  VISIT_TYPE_DESCRIPTION  INSITUTION_CODE ADMISSION_DATE  DISCHARGE_DATE  LENGTH_OF_STAY  CASE_NO
PATIENT_ID1 Inpatient   A   20130225    20130225    0   CASE_NO1
PATIENT_ID1 Inpatient   D   20130225    20130228    3   CASE_NO2
PATIENT_ID2 Inpatient   A   20130604    20130604    0   CASE_NO3
PATIENT_ID3 Inpatient   B   20130503    20130503    0   CASE_NO4
PATIENT_ID3 Inpatient   B   20130508    20130515    7   CASE_NO5
PATIENT_ID4 Inpatient   C   20130628    20130701    3   CASE_NO6
PATIENT_ID4 Inpatient   C   20130701    20130708    7   CASE_NO7", header = TRUE, stringsAsFactors = FALSE)

代码: 我写了一段代码来处理这些数据,但它仅有助于解决案例2和3,而不能解决案例1。

library(dplyr)
df %>% 
  group_by(PATIENT_ID) %>%
  mutate(ADMISSIONS_NUMBER_TOTAL= n(),
         ADMISSIONS_NUMBER_A  = sum(INSITUTION_CODE == "A"),
         ADMISSIONS_NUMBER_B  = sum(INSITUTION_CODE == "B"),
         ADMISSIONS_NUMBER_C  = sum(INSITUTION_CODE == "C"),
         ADMISSIONS_NUMBER_D  = sum(INSITUTION_CODE == "D"),
         ADMISSIONS_NUMBER_E  = sum(INSITUTION_CODE == "E"),
         ADMISSIONS_AVE_LOS   = sum(LENGTH_OF_STAY)/n()) %>%
  slice(1) %>% ungroup() %>%
  select(PATIENT_ID, ADMISSIONS_NUMBER_TOTAL:ADMISSIONS_AVE_LOS)

所需数据:

df <-  read.table(text = "
PATIENT_ID  ADMISSIONS_NUMBER_TOTAL ADMISSIONS_NUMBER_A ADMISSIONS_NUMBER_B ADMISSIONS_NUMBER_C ADMISSIONS_NUMBER_D ADMISSIONS_NUMBER_E ADMISSIONS_AVE_LOS
PATIENT_ID1 1   0   0   0   1   0   3
PATIENT_ID2 1   1   0   0   0   0   0
PATIENT_ID3 2   0   2   0   0   0   3.5
PATIENT_ID4 2   0   0   2   0   0   5", header = TRUE, stringsAsFactors = FALSE)

1 个答案:

答案 0 :(得分:1)

这是我使用tidyverse软件包套件(包括dplyr,但我还需要tidyrpurrr中的函数)来解决的方法。

第一步:解决“案例1”问题:

library(tidyverse)
tmp_df <- df %>%
  split(., interaction(.$PATIENT_ID, .$ADMISSION_DATE)) %>% # from base R
  map_df(~ arrange(.x, DISCHARGE_DATE) %>% tail(1)) %>% # from `purrr`
  group_by(PATIENT_ID)

第2步:计算一般摘要:

df_general <- tmp_df %>% 
    summarize(
      ADMISSIONS_NUMBER_TOTAL= n(),
      ADMISSIONS_AVE_LOS = mean(LENGTH_OF_STAY)
    )

第3步:计算机构特定的摘要:

df_inst <- tmp_df %>% 
  mutate(val = 1) %>%
  spread(INSITUTION_CODE, val, fill = 0) %>%  # from tidyr
  summarize_at(vars(A:D), sum) %>%
  select(PATIENT_ID, A:D) %>%
  rename_at(vars(A:D), ~paste0("ADMISSIONS_NUMBER_", .x))

第4步:将其合并在一起:

df_output <- full_join(df_general, df_inst) 

这时,如果顺序重要,则可以使用select重新排列列。