提醒我如何在几行中进行循环(例如套用等)

时间:2019-04-19 12:43:57

标签: r loops apply

我有一个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或dydyverse世界中的一些东西来解决问题。我真的不想要data.table的解决方案,除非它令人惊讶,否则我可能会开始考虑学习data.table。

3 个答案:

答案 0 :(得分:3)

使用基数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

答案 1 :(得分:2)

如果我们在您的代码中将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

答案 2 :(得分:2)

当我将相同或相似类型的对象(包括带列表的列表,带数据帧的数据框等)一起对待时,我通常会更好地完成这些任务。

有两种快速的整理方法可将字典放入数据框,这将使与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的{​​{1}}函数可以选择带后缀,这些后缀将附加到不是联接列但名称相同的列中。在这里,您可以查看哪个专业栏来自原始数据,哪个专业栏来自更正。

*_join

reprex package(v0.2.1)于2019-04-19创建