Напомните мне, как сделать цикл в несколько строк (например, применить и т. Д.) - PullRequest
0 голосов
/ 19 апреля 2019

У меня есть цикл for, использующий grepl для сопоставления аббревиатуры в столбце информационного кадра с ключом словаря и создания столбца со значением словаря этих ключей для привязки к исходному информационному фрейму.

У меня естьцикл for и код, который работает / дает мне то, что мне нужно.

#Example dataframe to loop over 
loop <- data.frame(
  acronym = c("cmr", "cmr", "den", "den", "nmw", "nmw"),
  profession = c("chinese medical practitioner", "chinese medical practitioner",
                 "dentist", "dentist", "medical practitioner", "nurse"),
  stringsAsFactors = FALSE
)
#The dictionary I created to provide values to each key
dic <- list(
  cmr = "chinese medical practitioner",
  den = "dentist",
  med = "medical practitioner",
  nmw = "nurse"
)

Цикл for со списком, созданным для хранения значений словаря для каждой итерации, где есть совпадение междуacronym в кадре данных и ключ в словаре.Затем я связываю незарегистрированный список значений с фреймом данных loop.Этот пример «исправляет» столбец profession в цикле, поэтому данные очищаются с использованием словаря и столбца acronym.

column <- list()
for (i in 1:length(loop$acronym)){
  for (j in 1:length(dic)){
    if (grepl(names(dic)[j], loop$acronym[i], loop$code)){
      column[i] <- dic[j]
    }
  }
}
cbind(unlist(column),loop)

НО, я хочу решить проблему с помощью apply иличто-то из загадочного мира.Я действительно не хочу решения из data.table, если только это не удивительно, тогда я мог бы начать изучать data.table.

Ответы [ 3 ]

3 голосов
/ 19 апреля 2019

Одним из способов использования базы R является использование stack, а затем merge.

merge(loop, stack(dic), by.x = "acronym", by.y = "ind")

#  acronym                   profession                       values
#1     cmr chinese medical practitioner chinese medical practitioner
#2     cmr chinese medical practitioner chinese medical practitioner
#3     den                      dentist                      dentist
#4     den                      dentist                      dentist
#5     nmw         medical practitioner                        nurse
#6     nmw                        nurse                        nurse

Где stack(dic) превращает именованный список в фрейм данных

stack(dic)
#                        values ind
#1 chinese medical practitioner cmr
#2                      dentist den
#3         medical practitioner med
#4                        nurse nmw
2 голосов
/ 19 апреля 2019

Мне часто везет с этими задачами, когда я рассматриваю объекты одного или сходного типа - списки со списками, кадры данных с кадрами данных и т. Д.

Существует пара быстрых способов получить словарь в фрейме данных, что облегчит объединение с данными loop. Первый просто берет имена списка и сглаженную версию списка и создает столбцы обоих.

library(dplyr)
library(purrr)

dict_df <- tibble(
  acronym = names(dic), 
  profession = flatten_chr(dic)
)
dict_df
#> # A tibble: 4 x 2
#>   acronym profession                  
#>   <chr>   <chr>                       
#> 1 cmr     chinese medical practitioner
#> 2 den     dentist                     
#> 3 med     medical practitioner        
#> 4 nmw     nurse

Вы также можете использовать более новую функцию tibble::enframe, которая создает кадры данных из отдельных векторов (как вы получаете после unlist) и также использует имена векторов в качестве столбца. Преимущество здесь в том, что он может хорошо вписаться в больший трубопроводный рабочий процесс - получить тот же результат, что и выше.

unlist(dic) %>% 
  tibble::enframe(name = "acronym", value = "profession")

Затем объедините исходные данные со словарем. Функции dplyr *_join могут иметь суффиксы, которые будут добавлены к столбцам, которые не являются столбцами соединения, но имеют одинаковые имена. Здесь можно увидеть, какая колонка профессий исходит из исходных данных, а какая из исправлений.

loop %>%
  left_join(dict_df, by = "acronym", 
            suffix = c("_loop", "_dict"))
#>   acronym              profession_loop              profession_dict
#> 1     cmr chinese medical practitioner chinese medical practitioner
#> 2     cmr chinese medical practitioner chinese medical practitioner
#> 3     den                      dentist                      dentist
#> 4     den                      dentist                      dentist
#> 5     nmw         medical practitioner                        nurse
#> 6     nmw                        nurse                        nurse

Создано в 2019-04-19 пакетом представ. (v0.2.1)

2 голосов
/ 19 апреля 2019

Если мы заменим list() на c() в вашем коде, чтобы сделать dic именованным вектором вместо списка, то мы можем сделать это в одной строке, используя имена векторов в качестве индексов:

dic <- c(
  cmr = "chinese medical practitioner",
  den = "dentist",
  med = "medical practitioner",
  nmw = "nurse"
)

loop$code = dic[loop$acronym]
loop
#   acronym                   profession                         code
# 1     cmr chinese medical practitioner chinese medical practitioner
# 2     cmr chinese medical practitioner chinese medical practitioner
# 3     den                      dentist                      dentist
# 4     den                      dentist                      dentist
# 5     nmw         medical practitioner                        nurse
# 6     nmw                        nurse                        nurse
...