【问题标题】:Custom lookup function in R not working within dplyr::mutate in RR 中的自定义查找函数在 R 中的 dplyr::mutate 中不起作用
【发布时间】:2020-04-04 05:27:21
【问题描述】:

我正在尝试使用自定义函数,它过滤数据框并从另一列中提取信息,在 dplyr::mutatedplyr version 0.8.3 内。我收到两种类型的错误。一个大数据框产生Error: Result must have length 32, not 1728 作为错误,另一个在以下示例代码中使用,不返回错误消息但返回错误匹配。

查找数据框

lookup.df<-data.frame(to.match=paste(letters[1:7],letters[8:14],sep = ""),
                       match=c("one","two","three","four","five","six","seven"))

lookup.df

  to.match match
1       ah   one
2       bi   two
3       cj three
4       dk  four
5       el  five
6       fm   six
7       gn seven

查找函数

lookup_function<-function(x){
  y<-lookup.df %>% 
    mutate_all(as.character) %>% 
    filter(to.match==x) %>% 
    pull(match)
  y
}

Vectorize(lookup_function)

终端运行

从终端运行函数确实会返回预期的结果。

> lookup_function("dk")
[1] "four"
> lookup_function("el")
[1] "five"

dplyr::mutate 运行

在 dplyr::mutate 中对不同的数据帧运行相同的函数不会返回预期的结果。

 live.df<-data.frame(to.match=rev(paste(letters[1:7],letters[8:14],sep = "")))

 live.df %>% 
   mutate(live.match=lookup_function(to.match))

  to.match live.match
1       gn       four
2       fm       four
3       el       four
4       dk       four
5       cj       four
6       bi       four
7       ah       four

代码应该,至少在这个例子中,应该返回 lookup.df 的匹配列,但相反,而是在每一行中返回 four

向量通过 Sapply

当通过sapply 进行管道传输时,该函数似乎确实返回了适当的结果。

c("dk","el") %>% sapply(lookup_function)
    dk     el 
"four" "five" 

我几乎不熟悉此类使用的自定义函数矢量化,所以我不确定这是否是此错误的根源。

修复此自定义函数以使其从查找数据帧返回正确信息的正确方法是什么?

【问题讨论】:

    标签: r dataframe dplyr custom-function


    【解决方案1】:

    关于将 OP 的函数与 Vectorize 一起使用,该函数将更新为 lookup_function &lt;- Vectorize(lookup_function),然后应用 OP 帖子中的代码或即时执行此操作

    library(dplyr)
    live.df %>% 
         mutate(live.match=Vectorize(lookup_function)(to.match))
    #  to.match live.match
    #1       gn      seven
    #2       fm        six
    #3       el       five
    #4       dk       four
    #5       cj      three
    #6       bi        two
    #7       ah        one
    

    但是,它会为每个匹配项过滤(filter(to.match==x))效率低下


    我们可以使用left_join

    library(dplyr)
    live.df %>%
         left_join(lookup.df)
    

    或使用match

    live.df %>%
          mutate(match = lookup.df$match[match(to.match, lookup.df$to.match)])
    

    也可以用在base R

    live.df$match <- with(live.df, lookup.df$match[match(to.match, lookup.df$to.match)])
    

    【讨论】:

    • 我能够为我的代码使用left_join 解决方案。 Vectorized 自定义函数也可以在示例代码中使用,在这种情况下我缺少赋值运算符。感谢您的帮助。
    • @IsraelGirón-Palacios 在这里,Vectorize 正在执行 lapply,这又是一个循环
    • 部分意图是避免合并,因为该项目中的其他数据帧不会具有硬设置的连接条件,因此它们最终会生成额外的错误数据行。使用您提出的left_join 解决方案,我刚刚过滤掉了有问题的行。到目前为止,我还没有遇到需要 left_joinfilter 以外的任何东西来进行最初预期的查找。我相信我会有一个需要grepl 才能在字符串中找到模式的方法,但可能还有另一种解决方法。
    • @IsraelGirón-Palacios match 会足够快,如果字符串不完全匹配,请使用 grepl
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-20
    相关资源
    最近更新 更多