如何使用在单独的 .yaml 文件中定义的条件过滤我的 R 数据?
How can I filter my R data using conditions that have been defined in seperate .yaml file?
情况:
所以我试图将我的代码分成两个不同的部分。第一部分包含所有参数,这些参数可能会随着代码一次又一次地重复使用而发生变化,然后是第二部分,即我希望保持不变的位。参数转到“.yaml”文件,其余参数硬编码到“.r”文件中。
使用代码一段时间后,很明显,代码中似乎半频繁更改的部分是我需要应用于我的数据的过滤器类型。例如,上个月我只需要 16 岁以上的人包含在我的数据集中,但现在我需要 8 到 55 岁之间的人。
我想做的是在我的“.yaml”文件中设置一些过滤条件,然后可以将其读入并应用于我的数据集,但我不太确定该怎么做。我试图用 titanic 数据集模拟这种情况(见下文)。
所以在这种情况下,我正在寻找的输出是一个新数据集 'filtered_data',它只包含幸存下来的男性,并且在 Class 列中没有 NA。
--- my_filters.yaml
filter_1:
- "Survived == 'Yes'" # show only people who have survived
filter_2:
- "Sex == 'Male'" # show only those who were male
filter_3:
- "!is.na(Class)" # show only those who do not have an 'na' in the class column
---
然后...
# my_code.r
library(dplyr)
library(yaml)
# read in data
data <- Titanic
# read in filters
filters <- yaml::read_yaml("my_filters.yaml")
filtered_data <- data%>%
dplyr::filter(filters$filter_1,
filters$filter_2,
filters$filter_3)
有人可以帮忙吗?我会非常感谢一些 tips/advice.
我认为一个问题是您使用的 Titanic
不是传统的数据框,而是 table。例如,如果我们使用 mtcars
,我们可以到达某个地方。 YAML 可能如下所示:
--- my_filters.yaml
filter_1:
- "cyl == 4" # show only 4 cylinder cars
filter_2:
- "disp > 100" # show only those with displacement > 100
filter_3:
- "!is.na(carb)" # show only those who do not have an 'na' in the carb column
---
然后,我们可以加载数据并制作过滤器。下面,我在 carb
中做了一些缺失的数据
library(dplyr)
library(yaml)
# read in data
data <- mtcars
data <- data %>%
mutate(carb = ifelse(carb == 8, NA, carb))
然后,我们读入过滤器,重要的是,解析文本。
filters <- yaml::read_yaml("~/Downloads/my_filters.yaml")
filters <- map(filters, ~parse(text=.x))
最后,我们可以在过滤器函数中评估过滤器:
filtered_data <- data%>%
dplyr::filter(eval(filters$filter_1),
eval(filters$filter_2),
eval(filters$filter_3))
filtered_data
# mpg cyl disp hp drat wt qsec vs am gear carb
# Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
# Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
# Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
# Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1
# Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
# Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
也许有人会 post 一个更简洁的版本,但这确实有效。
情况:
所以我试图将我的代码分成两个不同的部分。第一部分包含所有参数,这些参数可能会随着代码一次又一次地重复使用而发生变化,然后是第二部分,即我希望保持不变的位。参数转到“.yaml”文件,其余参数硬编码到“.r”文件中。使用代码一段时间后,很明显,代码中似乎半频繁更改的部分是我需要应用于我的数据的过滤器类型。例如,上个月我只需要 16 岁以上的人包含在我的数据集中,但现在我需要 8 到 55 岁之间的人。
我想做的是在我的“.yaml”文件中设置一些过滤条件,然后可以将其读入并应用于我的数据集,但我不太确定该怎么做。我试图用 titanic 数据集模拟这种情况(见下文)。
所以在这种情况下,我正在寻找的输出是一个新数据集 'filtered_data',它只包含幸存下来的男性,并且在 Class 列中没有 NA。
--- my_filters.yaml
filter_1:
- "Survived == 'Yes'" # show only people who have survived
filter_2:
- "Sex == 'Male'" # show only those who were male
filter_3:
- "!is.na(Class)" # show only those who do not have an 'na' in the class column
---
然后...
# my_code.r
library(dplyr)
library(yaml)
# read in data
data <- Titanic
# read in filters
filters <- yaml::read_yaml("my_filters.yaml")
filtered_data <- data%>%
dplyr::filter(filters$filter_1,
filters$filter_2,
filters$filter_3)
有人可以帮忙吗?我会非常感谢一些 tips/advice.
我认为一个问题是您使用的 Titanic
不是传统的数据框,而是 table。例如,如果我们使用 mtcars
,我们可以到达某个地方。 YAML 可能如下所示:
--- my_filters.yaml
filter_1:
- "cyl == 4" # show only 4 cylinder cars
filter_2:
- "disp > 100" # show only those with displacement > 100
filter_3:
- "!is.na(carb)" # show only those who do not have an 'na' in the carb column
---
然后,我们可以加载数据并制作过滤器。下面,我在 carb
library(dplyr)
library(yaml)
# read in data
data <- mtcars
data <- data %>%
mutate(carb = ifelse(carb == 8, NA, carb))
然后,我们读入过滤器,重要的是,解析文本。
filters <- yaml::read_yaml("~/Downloads/my_filters.yaml")
filters <- map(filters, ~parse(text=.x))
最后,我们可以在过滤器函数中评估过滤器:
filtered_data <- data%>%
dplyr::filter(eval(filters$filter_1),
eval(filters$filter_2),
eval(filters$filter_3))
filtered_data
# mpg cyl disp hp drat wt qsec vs am gear carb
# Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
# Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
# Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
# Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1
# Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
# Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
也许有人会 post 一个更简洁的版本,但这确实有效。