Как я могу использовать Tidyverse для вставки значений, которые находятся между указанным диапазоном и еще не существуют в интересующем столбце - PullRequest
3 голосов
/ 03 мая 2020

У меня большой тиббл с сгруппированными данными. Каждая группа включает 12 рядов. Третий столбец таблицы должен иметь значения от 1 до 12. В большинстве строк все строки в столбце 3 заполнены, а в некоторых нет. Для тех строк с отсутствующими данными (NA) я хотел бы использовать dplyr, чтобы вставить правильное значение. Моя задача состоит в том, чтобы значения в столбце 3 не обязательно были в порядке нумерации c, поэтому я должен найти значения, которые еще не существуют в, и затем вставить их соответствующим образом.

Я подготовил репрезентацию для демонстрации что я пытаюсь описать В моем примере в группе B отсутствуют последние два значения в столбце 3. Единственные значения, которые еще не существуют в столбце 3, это 4 и 7. Поэтому я хотел бы найти способ определить, какие значения можно вставить, а затем использовать мутировать, чтобы обновить значение NA до неиспользованного значения. Это все часть моих усилий по удовлетворению требований к данным фреймов данных mlo git.

library(tidyverse)

df_BEFORE <- tibble( key = c("A","A","A","A","A","A","A","A","A","A","A","A","B","B","B","B","B","B","B","B","B","B","B","B"),y=c(2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2), z=c(1,2,3,4,5,6,7,8,9,10,11,12,2,11,3,6,12,8,9,10,1,5,NA,NA))

print(df_BEFORE, n=24)
#> # A tibble: 24 x 3
#>    key       y     z
#>    <chr> <dbl> <dbl>
#>  1 A         2     1
#>  2 A         2     2
#>  3 A         2     3
#>  4 A         2     4
#>  5 A         2     5
#>  6 A         2     6
#>  7 A         2     7
#>  8 A         2     8
#>  9 A         2     9
#> 10 A         2    10
#> 11 A         2    11
#> 12 A         2    12
#> 13 B         2     2
#> 14 B         2    11
#> 15 B         2     3
#> 16 B         2     6
#> 17 B         2    12
#> 18 B         2     8
#> 19 B         2     9
#> 20 B         2    10
#> 21 B         2     1
#> 22 B         2     5
#> 23 B         2    NA
#> 24 B         2    NA

df_AFTER <- df_BEFORE %>% 
  group_by(key) 


target_df  <- tibble( key = c("A","A","A","A","A","A","A","A","A","A","A","A","B","B","B","B","B","B","B","B","B","B","B","B"),y=c(2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2), z=c(1,2,3,4,5,6,7,8,9,10,11,12,2,11,3,6,12,8,9,10,1,5,4,7))

print(target_df, n=24)
#> # A tibble: 24 x 3
#>    key       y     z
#>    <chr> <dbl> <dbl>
#>  1 A         2     1
#>  2 A         2     2
#>  3 A         2     3
#>  4 A         2     4
#>  5 A         2     5
#>  6 A         2     6
#>  7 A         2     7
#>  8 A         2     8
#>  9 A         2     9
#> 10 A         2    10
#> 11 A         2    11
#> 12 A         2    12
#> 13 B         2     2
#> 14 B         2    11
#> 15 B         2     3
#> 16 B         2     6
#> 17 B         2    12
#> 18 B         2     8
#> 19 B         2     9
#> 20 B         2    10
#> 21 B         2     1
#> 22 B         2     5
#> 23 B         2     4
#> 24 B         2     7

Обновление: у меня есть рабочее решение, но его уродливое мурлыканье может помочь


library(tidyverse)

df_BEFORE <- tibble( key = c("A","A","A","A","A","A","A","A","A","A","A","A","B","B","B","B","B","B","B","B","B","B","B","B"),y=c(2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2), z=c(1,2,3,4,5,6,7,8,9,10,11,12,2,11,3,6,12,8,9,10,1,5,NA,NA))

print(df_BEFORE, n=24)
#> # A tibble: 24 x 3
#>    key       y     z
#>    <chr> <dbl> <dbl>
#>  1 A         2     1
#>  2 A         2     2
#>  3 A         2     3
#>  4 A         2     4
#>  5 A         2     5
#>  6 A         2     6
#>  7 A         2     7
#>  8 A         2     8
#>  9 A         2     9
#> 10 A         2    10
#> 11 A         2    11
#> 12 A         2    12
#> 13 B         2     2
#> 14 B         2    11
#> 15 B         2     3
#> 16 B         2     6
#> 17 B         2    12
#> 18 B         2     8
#> 19 B         2     9
#> 20 B         2    10
#> 21 B         2     1
#> 22 B         2     5
#> 23 B         2    NA
#> 24 B         2    NA

get_index <- function(c,j){
  case_when(
    is.na(j) ~ 0,
    j == 0 ~ 0,
    j ==1 ~ setdiff(1:12,c)[1],
    j ==2 ~ setdiff(1:12,c)[2],
    j ==3 ~ setdiff(1:12,c)[3],
    j ==4 ~ setdiff(1:12,c)[4],
    j ==5 ~ setdiff(1:12,c)[5],
    j ==6 ~ setdiff(1:12,c)[6],
    j ==7 ~ setdiff(1:12,c)[7],
    j ==8 ~ setdiff(1:12,c)[8],
    j ==9 ~ setdiff(1:12,c)[9],
    j ==10 ~ setdiff(1:12,c)[10],
    j ==11 ~ setdiff(1:12,c)[11]
  )
}


df_BEFORE %>% 
  group_by(key) %>% 
  mutate(seed = 1) %>% 
  mutate(flag = if_else(!is.na(z),0,seed)) %>% 
  mutate(j = flag + lag(flag)) %>%
  mutate(temp = z) %>%
  mutate(new_z = if_else(j==1,setdiff(1:12,temp)[1],
                 if_else(j==2,setdiff(1:12,temp)[2],
                 if_else(j==3,setdiff(1:12,temp)[3],
                 if_else(j==4,setdiff(1:12,temp)[4],
                 if_else(j==2,setdiff(1:12,temp)[5],
                 if_else(j==2,setdiff(1:12,temp)[6],
                 if_else(j==2,setdiff(1:12,temp)[7],
                 if_else(j==2,setdiff(1:12,temp)[8],
                 if_else(j==2,setdiff(1:12,temp)[9],
                 if_else(j==2,setdiff(1:12,temp)[2],0L
                                 ))))))))))) %>%
  mutate(z= if_else(is.na(z),as.numeric(new_z),z)) %>%
  select(-j, -new_z,-temp, -flag, -seed) %>% 
  print(n=24)
#> # A tibble: 24 x 3
#> # Groups:   key [2]
#>    key       y     z
#>    <chr> <dbl> <dbl>
#>  1 A         2     1
#>  2 A         2     2
#>  3 A         2     3
#>  4 A         2     4
#>  5 A         2     5
#>  6 A         2     6
#>  7 A         2     7
#>  8 A         2     8
#>  9 A         2     9
#> 10 A         2    10
#> 11 A         2    11
#> 12 A         2    12
#> 13 B         2     2
#> 14 B         2    11
#> 15 B         2     3
#> 16 B         2     6
#> 17 B         2    12
#> 18 B         2     8
#> 19 B         2     9
#> 20 B         2    10
#> 21 B         2     1
#> 22 B         2     5
#> 23 B         2     4
#> 24 B         2     7

Создано в 2020-05-03 представляет пакет (v0.3.0)

1 Ответ

0 голосов
/ 05 мая 2020

У вас есть правильная идея в ваших комментариях, но вместо if_else() вы можете использовать replace():

df_BEFORE %>% 
  group_by(key) %>% 
  mutate(z = replace(z, is.na(z), setdiff(1:12, z)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...