1

我正在探索来自 Pokemon API 的数据(实际上并未使用 API,只是从 github 中提取 .csv 文件)。在一个包含每个 Pokemon 类型的窄格式(一个 Pokemon 最多可以有两种类型)的文件中pokemon_types.csv,类型被编码为整数(本质上是因子)。我想通过使用types.csv同样来自 API的查找表id(identifier想用作标签。

> head(read_csv(path("pokemon_types.csv")), 10)
# A tibble: 10 x 3
   pokemon_id type_id  slot
        <dbl>   <dbl> <dbl>
 1          1      12     1
 2          1       4     2
 3          2      12     1
 4          2       4     2
 5          3      12     1
 6          3       4     2
 7          4      10     1
 8          5      10     1
 9          6      10     1
10          6       3     2
> head(read_csv(path("types.csv")))
# A tibble: 6 x 4
     id identifier generation_id damage_class_id
  <dbl> <chr>              <dbl>           <dbl>
1     1 normal                 1               2
2     2 fighting               1               2
3     3 flying                 1               2
4     4 poison                 1               2
5     5 ground                 1               2
6     6 rock                   1               2

当我单独管道所有步骤时,我的代码可以工作,但是由于我要执行这个标记步骤至少十几次,所以我试图将它放入一个函数中。问题是,当我改为调用该函数时(据我所知,它具有完全相同的步骤)它会引发object not found错误。

设置:

library(readr)
library(magrittr)
library(dplyr)
library(tidyr)

options(readr.num_columns = 0)

# Append web directory to filename
path <- function(x) {
  paste0("https://raw.githubusercontent.com/",
         "PokeAPI/pokeapi/master/data/v2/csv/", x)
}

违规功能:

# Use lookup table to label factor variables
label <- function(data, variable, lookup) {
  mutate(data, variable = factor(variable, 
                                 levels = read_csv(path(lookup))$id,
                                 labels = read_csv(path(lookup))$identifier))
}

此版本不使用该功能,适用:

df.types <-
  read_csv(path("pokemon_types.csv")) %>%
  mutate(type_id = factor(type_id, 
                          levels = read_csv(path("types.csv"))$id,
                          labels = read_csv(path("types.csv"))$identifier)) %>%
  spread(slot, type_id)

head(df.types)

它返回:

# A tibble: 6 x 3
  pokemon_id `1`   `2`   
       <dbl> <fct> <fct> 
1          1 grass poison
2          2 grass poison
3          3 grass poison
4          4 fire  NA    
5          5 fire  NA    
6          6 fire  flying

此版本使用该功能,不会:

df.types <-
  read_csv(path("pokemon_types.csv")) %>%
  label(type_id, "types.csv") %>%
  spread(slot, type_id)

它返回:

Error in factor(variable, 
                levels = read_csv(path(lookup))$id, 
                labels = read_csv(path(lookup))$identifier) : 
  object 'type_id' not found 

我知道这里有几件事可能不是最理想的(lookup例如每次下载两次),但我更感兴趣的是为什么一个看起来与某些书面代码相同的函数使它不再工作。我确信我只是犯了一个愚蠢的错误。

4

1 回答 1

1

感谢有用的评论,我能够了解所有关于非标准评估并找出解决方案:

label <- function(data, variable, lookup) {
  variable <- enquo(variable)
  data %>%
    mutate(!!variable := factor(!!variable, 
                                 levels = read_csv(path(lookup))$id,
                                 labels = read_csv(path(lookup))$identifier))
}

关键特性是enquo(),它充当“准引用”,!!,它“取消引用”变量,以便可以通过参数解释它,以及:=,它允许在双方都取消引用。

我尝试并未能实现dplyr完全避免的解决方案,但至少这是可行的。

于 2019-03-23T04:36:27.380 回答