Создайте новую строку на основе разницы между предыдущими строками в R

#r #tidyverse #rvest

Вопрос:

Я извлек html-таблицу с помощью rvest и получил фрейм данных, подобный этому:

 data <- tribble(
  ~ward,               ~patient_count, ~date,
  "ICU",                10,            "2021-01-01",
  "of which ventilated", 6,            "2021-01-01",
  "other",               4,            "2021-01-01", 
  "ICU",                 8,            "2021-01-02",
  "of which ventilated", 2,            "2021-01-02",
  "other",               4,            "2021-01-02", 
)
 

Я недоволен такой компоновкой данных. Моей первой мыслью было попытаться получить что-то подобное:

 data <- tribble(
  ~ward,               ~patient_count, ~ventilated, ~date,
  "ICU",                 4,            FALSE,       "2021-01-01",
  "ICU",                 6,            TRUE,        "2021-01-01",
  "other",               4,            FALSE,       "2021-01-01",
  "ICU",                 6,            FALSE,       "2021-01-02",
  "ICU",                 2,            TRUE,        "2021-01-02",
  "other",               4,            FALSE,       "2021-01-02",
)
 

Я попытался установить ventilated тег следующим образом:

 data <- data %>% 
  mutate(
    ventilated = case_when(ward == "of which ventilated" ~ TRUE,
                           ward != "of which ventilated" ~ FALSE)
  ) 
 

Однако я не совсем уверен, как лучше всего правильно рассчитать цифры.

Комментарии:

1. Я считаю, что вам было бы лучше развернуть данные в более широкую строку с одной строкой на дату, тогда манипулирование именами и значениями столбцов будет тривиальным, и вы можете повернуть их обратно в более длинную, если действительно захотите

Ответ №1:

Используя case_when аналогично,(я сделал это как patient_count_2 )

Интересно, есть ли более подробное правило, которое нужно изменить patient_count . Благодаря @r2evans, рассмотреть надежный способ, если формат данных может отличаться от data предоставленного вами? Или всегда, как ICU тогда of which ventilated ?

 data %>%
  mutate(patient_count_2 = case_when(
    lead(ward) == "of which ventilated" ~ patient_count - lead(patient_count),
    TRUE ~ patient_count
  ),
  ventilated = (ward == "of which ventilated"), 
  ward = ifelse(ward == "of which ventilated", "ICU", ward)
  )


  ward  patient_count date       patient_count_2 ventilated
  <chr>         <dbl> <chr>                <dbl> <lgl>     
1 ICU              10 2021-01-01               4 FALSE     
2 ICU               6 2021-01-01               6 TRUE      
3 other             4 2021-01-01               4 FALSE     
4 ICU               8 2021-01-02               6 FALSE     
5 ICU               2 2021-01-02               2 TRUE      
6 other             4 2021-01-02               4 FALSE   
 

Комментарии:

1. Использование lead(.) кажется хрупким в порядке строк, есть ли способ сделать его более надежным для этого? (Это также казалось бы уместным group_by(date) или подобным образом.)

2. @r2evans Я этого не заметил. Большое спасибо. Я попробую надежный способ :D.

Ответ №2:

Может быть, попробуйте повернуть данные:

 library(tidyr)

data <- tribble(
   ~ward,               ~patient_count, ~date,
   "ICU",                10,            "2021-01-01",
   "of which ventilated", 6,            "2021-01-01",
   "other",               4,            "2021-01-01", 
   "ICU",                 8,            "2021-01-02",
   "of which ventilated", 2,            "2021-01-02",
   "other",               4,            "2021-01-02", 
)

pivot_wider(data, names_from = "ward", values_from = "patient_count")


# A tibble: 2 × 4
  date         ICU `of which ventilated` other
  <chr>      <dbl>                 <dbl> <dbl>
1 2021-01-01    10                     6     4
2 2021-01-02     8                     2     4