【问题标题】:Applying interaction() to user-specified column from within a tidyverse pipe从 tidyverse 管道中将交互()应用于用户指定的列
【发布时间】:2021-10-15 17:28:38
【问题描述】:

作为一个更大项目的一部分,我正在尝试根据用户指定变量的交互在名为“unique_id”的 data.frame 中创建一个新列。在这个用例中,所需的变量数量和名称会因每个用户而异,因此这种灵活性很重要。一些 data.frames,例如我在示例中制作的玩具,甚至会带有一个“唯一 id”变量,但这种情况很少见。我在示例中包含了我想要的输出是什么。

考虑一下这个玩具 data.frame:

mini_df <- data.frame(
  lat = c(41.23,37.37,41.23,39.01,32.00),
  lon = c(-120.79,-120.68,-120.79,-119.13,-120.00),
  station_id = c(300,527,300,228,72)
)

在适当的功能之外,很容易做这样的事情:

out_of_function_test_df <- mini_df %>%
  mutate(id = interaction(lat, lon))

产生我想要的,即:

    lat     lon station_id            id
1 41.23 -120.79        300 41.23.-120.79
2 37.37 -120.68        527 37.37.-120.68
3 41.23 -120.79        300 41.23.-120.79
4 39.01 -119.13        228 39.01.-119.13
5 32.00 -120.00         72       32.-120

我需要它在用户指定交互变量的函数中工作。

我阅读了许多堆栈交换帖子,这些帖子解决了与我的一些重要差异类似的问题。其他问题涉及 mutate 以外的动词,尝试应用不同的功能,或者不解决 多个 用户指定变量的问题。

在阅读了这些,尝试了很多事情并阅读了this之后,我能想到的最好的方法如下:

create_unique_id <- function(df,
                             metadata_coords,
                             unique_id_coords) {
  df <- df %>%
    mutate_(id = interp(~interaction(args), # causes error with or without tilde
                        args = c("list", lapply(unique_id_coords, as.name))))

  return(df)
}

这会产生错误:

Error in unique.default(x, nmax = nmax) : 
  unique() applies only to vectors

如果有帮助,这里是完整的回溯:

22.
unique.default(x, nmax = nmax) 
21.
unique(x, nmax = nmax) 
20.
factor(x) 
19.
as.factor(args[[i]]) 
18.
interaction(list("list", lat, lon)) 
17.
mutate_impl(.data, dots, caller_env()) 
16.
mutate.tbl_df(tbl_df(.data), ...) 
15.
mutate(tbl_df(.data), ...) 
14.
as.data.frame(mutate(tbl_df(.data), ...)) 
13.
mutate.data.frame(.data, !!!dots) 
12.
mutate(.data, !!!dots) 
11.
mutate_.data.frame(., id = interp(~interaction(args), args = c("list", 
    lapply(unique_id_coords, as.name)))) 
10.
mutate_(., id = interp(~interaction(args), args = c("list", lapply(unique_id_coords, 
    as.name)))) 
9.
function_list[[k]](value) 
8.
withVisible(function_list[[k]](value)) 
7.
freduce(value, `_function_list`) 
6.
`_fseq`(`_lhs`) 
5.
eval(quote(`_fseq`(`_lhs`)), env, env) 
4.
eval(quote(`_fseq`(`_lhs`)), env, env) 
3.
withVisible(eval(quote(`_fseq`(`_lhs`)), env, env)) 
2.
df %>% mutate_(id = interp(~interaction(args), args = c("list", 
    lapply(unique_id_coords, as.name)))) 
1.
create_unique_id(df = mini_df, metadata_coords = c("lat", "lon", 
    "station_id"), unique_id_coords = c("lat", "lon"))

我没有足够的背景知识来帮助我。我很困惑,因为问题似乎在 interact() 函数的深处。 interact() 一路调用 unique() (这是有道理的),但 unique() 最终失败了。不知何故,在我的函数中对 interact() 的初始调用与在函数外部时不同,但我不确定如何。

【问题讨论】:

    标签: r dplyr tidyverse


    【解决方案1】:

    tidyr::unite() 的这个应用程序有帮助吗?

    create_unique_id <- function(df, 
                                 unique_id_coords) {
      df <- df %>%
        tidyr::unite("id", {{ unique_id_coords }}, remove = FALSE)
      return(df)
    }
    

    结果

    create_unique_id(mtcars, unique_id_coords = c(wt, qsec)) %>% head()
    
                       mpg cyl disp  hp drat          id    wt  qsec vs am gear carb
    Mazda RX4         21.0   6  160 110 3.90  2.62_16.46 2.620 16.46  0  1    4    4
    Mazda RX4 Wag     21.0   6  160 110 3.90 2.875_17.02 2.875 17.02  0  1    4    4
    Datsun 710        22.8   4  108  93 3.85  2.32_18.61 2.320 18.61  1  1    4    1
    Hornet 4 Drive    21.4   6  258 110 3.08 3.215_19.44 3.215 19.44  1  0    3    1
    Hornet Sportabout 18.7   8  360 175 3.15  3.44_17.02 3.440 17.02  0  0    3    2
    Valiant           18.1   6  225 105 2.76  3.46_20.22 3.460 20.22  1  0    3    1
    

    【讨论】:

    • 是的!这解决了问题。我很高兴有这么简单的解决方法。我肯定是多虑了。非常感谢!
    【解决方案2】:

    这是另一个使用省略号 ... 的选项:

    library(rlang)
    create_unique_id <- function(df, ...){
      
      df %>% 
        mutate(id = paste(!!! ensyms(...), sep = "_"))
      
    }
    

    输出

    create_unique_id(mtcars, cyl, hp, vs) %>% head()
    
                       mpg cyl disp  hp drat    wt  qsec vs am gear carb      id
    Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4 6_110_0
    Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4 6_110_0
    Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1  4_93_1
    Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1 6_110_1
    Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2 8_175_0
    Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1 6_105_1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-16
      • 1970-01-01
      • 2018-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多