Как изменить NA идентификатора на символьное значение на основе значений / характеристик других идентификаторов в R?

У меня проблема с отсутствующими значениями в моем наборе данных. По какой-то причине в нескольких идентификаторах отсутствует значение в столбце "Имена". Это странно, потому что другие идентификаторы (с тем же КОДОМ (в моем наборе данных больше кодов (> 10K) и в том же году (6 вариантов для лет)) имеют значение в этом столбце.

Может ли кто-нибудь помочь мне выяснить код, чтобы идентификаторы с отсутствующими значениями в столбце «Имена» получали такое же значение символа в столбце «Имена», если другие идентификаторы с тем же кодом и годом имеют значение в этом столбец?

Например: NA в строке 4; должен измениться на «Больница»; на основе того же кода и года другого идентификатора (в моем исходном фрейме данных есть идентификатор с 2013 и код 01 с именем «Больница»; в противном случае он должен остаться NA).

Примечание: это панельные данные, поэтому каждый идентификатор может находиться в наборе данных в течение нескольких лет (и строк; каждый год - это одна строка), и не все входят в каждый год. В моем фрейме данных также есть больше переменных.

> dput(Dataframe[1:7, ])
structure(list(ID = structure(c(1, 2, 2, 2, 2, 2, 2), format.spss = "F9.3"), CODE = c("01", "01", "01","01", "01", "01", "01"), Year = structure(c(2018, 2014, 2018, 2013, 2013, 2015, 2015), format.spss = "F9.3"), Quarter = structure(c(3, 4, 4, 4, 3, 4, 3), format.spss = "F9.3"), Size = c(24.5, 23.25, 24.5, 30, 30, 19.25, 19.25), Names = c("Hospital", "Hospital", "Hospital", NA, "Hospital", NA, "Hospital")), row.names = c(NA, -7L), class = c("tbl_df", "tbl", "data.frame"

A tibble: 7 x 8
  ID Gender CODE Year Quarter Size Names
       <dbl>      <dbl> <dttm>              <chr>            <dbl>           <dbl>           <dbl> <chr>                  
1  1          2 01          2018               3            24.5 Hospital
2  2          1 01          2014               4            23.2 Hospital
3  2          1 01          2018               4            24.5 Hospital
4  2          1 01          2013               4            30   NA                     
5  2          1 01          2013               3            30   Hospital
6  2          1 01          2015               4            19.2 NA                     
7  2          1 01          2015               3            19.2 Hospital

Выбор и проверка отдельных строк - это слишком много работы, у меня более 1,1 миллиона строк ..

Изменить: также можно перенести столбец «имена» в 1, если он имеет (символьное) значение, и 0, если нет.

Спасибо!


person Student0172    schedule 16.05.2020    source источник


Ответы (2)


Я не совсем уверен, потому что в вашем примере все имена совпадают, но я думаю, что это может сделать то, что вы ищете.

В приведенном ниже примере я изменил фамилию «Не больница».

df <- structure(list(ID = structure(c(1, 2, 2, 2, 2, 2, 2), format.spss = "F9.3"), CODE = c("01", "01", "01","01", "01", "01", "01"), Year = structure(c(2018, 2014, 2018, 2013, 2013, 2015, 2015), format.spss = "F9.3"), Quarter = structure(c(3, 4, 4, 4, 3, 4, 3), format.spss = "F9.3"), Size = c(24.5, 23.25, 24.5, 30, 30, 19.25, 19.25), Names = c("Hospital", "Hospital", "Hospital", NA, "Hospital", NA, "Not Hospital")), row.names = c(NA, -7L), class = c("tbl_df", "tbl", "data.frame") ) 

Оригинал

# A tibble: 7 x 6
     ID CODE   Year Quarter  Size Names       
  <dbl> <chr> <dbl>   <dbl> <dbl> <chr>       
1     1 01     2018       3  24.5 Hospital    
2     2 01     2014       4  23.2 Hospital    
3     2 01     2018       4  24.5 Hospital    
4     2 01     2013       4  30   NA          
5     2 01     2013       3  30   Hospital    
6     2 01     2015       4  19.2 NA          
7     2 01     2015       3  19.2 Not Hospital

Вот код для обновления имен.

df %>%
  filter(!is.na(Names)) %>%
  select(CODE, Year, Names)  %>%
  group_by_all() %>%
  summarise() %>%
  right_join(df, by = c("CODE", "Year")) %>%
  rename(Names = Names.x) %>%
  select(-Names.y)

Выход:

# A tibble: 7 x 6
# Groups:   CODE, Year [4]
  CODE   Year Names           ID Quarter  Size
  <chr> <dbl> <chr>        <dbl>   <dbl> <dbl>
1 01     2018 Hospital         1       3  24.5
2 01     2014 Hospital         2       4  23.2
3 01     2018 Hospital         2       4  24.5
4 01     2013 Hospital         2       4  30  
5 01     2013 Hospital         2       3  30  
6 01     2015 Not Hospital     2       4  19.2
7 01     2015 Not Hospital     2       3  19.2
person dpmcsuss    schedule 16.05.2020
comment
Привет, dpmcsuss, в моем примере фрейма данных это сработало! Я собираюсь проверить, работает ли он сейчас с моим большим набором данных с другим именем и кодами. Спасибо за ваши усилия! - person Student0172; 16.05.2020

Насколько я понимаю, есть несколько способов подойти к этой проблеме. Однако я предпочитаю следующее решение.

Первый шаг - разделить фрейм данных на два. Один фрейм данных содержит только строки без NA в столбце Names, а другой - только строки с NA в столбце Names. Затем вы просто выполняете поиск комбинаций CODE YEAR в первом и возвращаете имя соответствующей строки. Первый - собрать строки, содержащие NA, и использовать их для поиска комбинаций кода и года.

# Your data frame
df <- 

# Split df
df.with.nas <- df[ is.na(df$Names) ,]
df.without.nas <- df[ !is.na(df$Names) ,]

# Define function to separat logic
get.name <- function(row) {
  # row is an atomic vector. Hence we have to use row["<SELECTOR>"]
  result <- subset(df.without.nas, CODE == row["CODE"] & Year == row["Year"])
  return(result["Names"])
}

# Finally, search and return.
row.axis <- 1
df.with.nas$Names <- apply(df.with.nas, row.axis, get.name)

# Combine the dfs
df <- rbind(
  df.with.nas, df.without.nas)

У этого решения есть недостаток. Что должно произойти, когда мы найдем дубликаты?

Надеюсь, это пригодится!

person MacOS    schedule 16.05.2020