【问题标题】:How to avoid overwriting a variable by a tibble column name?如何避免用 tibble 列名覆盖变量?
【发布时间】:2021-12-18 03:18:40
【问题描述】:

我观察到 filter() 函数的行为让我有点困扰。

我想从 tibble 中选择符合简单标准的行,它们在特定列中有一些值。该值存储在一个变量中。超级简单的东西。问题是我的变量名与 tibble 的列名相同,这会产生我没想到的行为。

>block 
[1] 41
>msg %>% filter(text == "trial_run" & block == block)
# A tibble: 42 × 4
    ...1 block    time text     
   <dbl> <dbl>   <dbl> <chr>    
 1    14     1 1149175 trial_run
 2    30     2 1164422 trial_run
 3    46     3 1193408 trial_run
 4    62     4 1199713 trial_run
 5    78     5 1211763 trial_run
 6    94     6 1218312 trial_run
 7   110     7 1222947 trial_run
 8   126     8 1236795 trial_run
 9   142     9 1247513 trial_run
10   158    10 1254297 trial_run
# … with 32 more rows

我假设 block == block 产生类似 1 == 1 的重言式,因此我的块标准没有应用。一个简单的解决方案就是更改块变量的名称。

> blk <- block
> msg %>% filter(text == "trial_run" & block == blk)
# A tibble: 1 × 4
   ...1 block    time text     
  <dbl> <dbl>   <dbl> <chr>    
1   654    41 1513347 trial_run

但我觉得这种情况可能会导致我将来遇到难以跟踪的错误。我究竟做错了什么?我以后如何避免这个问题(除了创建唯一的变量和列名)?

【问题讨论】:

    标签: r filter tidyverse


    【解决方案1】:

    过滤器命令具有.data.env“代词”,您可以使用它们来明确变量的来源。试试

    msg %>% filter(text == "trial_run" & .data$block == .env$block)
    

    .data 表示它来自 data.frame,.env 表示它是来自环境的值。您可以在rlang help 中了解更多信息。该页面上有一个类似的示例。

    【解决方案2】:

    我们可以逃脱!!

    library(dplyr)
    block <- 4
    msg %>% 
        filter(text == "trial_run" & block == !!block)
    

    -输出

    ...1 block    time      text
    4   62     4 1199713 trial_run
    

    或者可以从 globalenv 访问变量

    msg %>% 
        filter(text == "trial_run" & block == .GlobalEnv$block)
    

    -输出

    ...1 block    time      text
    4   62     4 1199713 trial_run
    

    数据

    msg <- structure(list(...1 = c(14L, 30L, 46L, 62L, 78L, 94L, 110L, 126L, 
    142L, 158L), block = 1:10, time = c(1149175L, 1164422L, 1193408L, 
    1199713L, 1211763L, 1218312L, 1222947L, 1236795L, 1247513L, 1254297L
    ), text = c("trial_run", "trial_run", "trial_run", "trial_run", 
    "trial_run", "trial_run", "trial_run", "trial_run", "trial_run", 
    "trial_run")), class = "data.frame", row.names = c("1", "2", 
    "3", "4", "5", "6", "7", "8", "9", "10"))
    

    【讨论】:

    • ,@akrun 但是使用相同的名称不是一个好习惯吗?我们应该简单地重命名变量吗?还是在某些情况下我们必须使用列名 == 变量名?
    • @TarJae 我会避免使用相同的列名命名,因为这样更容易并且会避免任何错误。 OP 必须指定与对象相同的列名的情况很少见。
    猜你喜欢
    • 2014-03-21
    • 2021-08-25
    • 2021-11-10
    • 2015-05-15
    • 1970-01-01
    • 2013-06-02
    • 1970-01-01
    • 2020-05-18
    • 2022-01-22
    相关资源
    最近更新 更多