两个参数age
和gender
的简化代码;但是,我想仅通过gender
或age
选择案例;我在想如何重载到getIDs(age)
和getIDs(gender)
,而不会一次又一次地相乘相同的代码;假设您有50个参数等;我试过getIDs(age, "")
,但我不是个好主意
getIDs <- function(age, gender) {
# https://stackoverflow.com/a/40330110/54964
ageIDs <- c(1,2,3)
genderIDs # dummy code here to indicate that do not use genderIDs if gender ""
intersect(ageIDs, genderIDs)
}
主要数据
ID,Age,Gender
100,69,male
101,75,female
102,84,female
103,,male
104,66,female
数据2
DF <- structure(list(ID = 100:104, Age = c(69L, 75L, 84L, NA, 66L), Gender =
c("male", "female", "female", "male", "female")), .Names = c("ID", "Age",
"Gender"), row.names = c(NA, -5L), class = "data.frame")
同样适用于年龄:如果age==""
,请不要包含subset
ageIDs。
所有男性的某些参数都很棒,因此您无需明确"male", "male", ...
。
我认为这个策略对50个参数非常具有挑战性,因此仍然需要更好的方法
getIDs <- function(age, gender) {
# https://stackoverflow.com/a/40330110/54964
# So if you called this as getIDs(c(20, 30), "male")
# You'd get the ids of all males with age >= 20 and <= 30
#
# NULL = ALL
# getIDs(age = c(1,2), gender = NULL)
# getIDs(age = NULL, gender = "male")
data <- read.csv("/home/masi/data.csv",header = TRUE,sep = ",")
if (is.null(gender)) {
genderIDs <- data$ID
} else {
gender <- data$Gender == gender
genderIDs <- data[which(gender), ]$ID
}
if (is.null(age)) {
age <- c(0,130)
}
if (length(age) == 1) {
ages <- data$Age == age
} else {
ages <- (data$Age >= age[1] & data$Age <= age[2])
}
ageIDs <- data[which(ages), ]$ID
intersect(ageIDs, genderIDs)
}
操作系统:Debian 8.5 答案 0 :(得分:5)
您可以为参数指定默认值并将其捕获到下游。
例如,如果您创建age = NULL
,则可以使用
if (is.null(age)) {
# do something
}
其他参数也是如此。另一个不错的选择是使用由NA
函数捕获的is.na
。
在讨论之后,五十个参数在任何情况下都是完整的。根据您的需要,您有多种选择。
如果所有参数都具有相同的数据类型,则可以使用命名向量,例如
x <- c(arg1 = "1", arg2 = "this")
如果您有不同的数据类型,并且您不希望它们被强制转换为一种类型(数字将被强制转换为字符,如果一个参数是字符,请尝试c(1, "2")
),您可以使用列表。< / p>
x <- list(par1 = 1,
par2 = "2",
par3 = factor(3),
par4 = TRUE)
在R中使用列表非常自然,您可以使用例如sapply
或lapply
。您可以找到所有数值
> x[sapply(x, is.numeric)]
$par1
[1] 1
或仅仅基于名称
> x[grepl(paste("par", 1:2, sep = "", collapse = "|"), names(x))]
$par1
[1] 1
$par2
[1] "2"
答案 1 :(得分:4)
遵循罗马的想法,我可能会使用一个列表:
library(data.table)
setDT(DF)
getIDs <- function(L) DF[L, on=names(L), ID]
用法:
> getIDs(list(Gender = "male"))
[1] 100 103
> getIDs(list(Gender = "male", Age = NA))
[1] 103
数据
DF = structure(list(ID = 100:104, Age = c(69L, 75L, 84L, NA, 66L),
Gender = c("male", "female", "female", "male", "female")), .Names = c("ID",
"Age", "Gender"), row.names = c(NA, -5L), class = "data.frame")
答案 2 :(得分:3)
使用dplyr
,您可以编写一个通用函数,您可以将您喜欢的任何条件作为字符串传递给函数,它将返回值。这可以轻松扩展到多个参数,只要您的条件字符串可以由dplyr评估(输出是使用您提供的数据框生成的in this question:
library(dplyr)
getIDs <- function(conditon)
{
data <- read.csv("/home/masi/data.csv", header = T)
df <- data %>% filter_(conditon) %>% .$ID
}
getIDs("Gender == 'male'")
# [1] 100 103
getIDs("Age > 30")
# [1] 100 101 102 104
getIDs("Gender == 'male' & Age > 30")
# [1] 100
如果你不需要在函数中读入data
,那么函数可以写成
getIDs <- . %>% filter_(DF, .) %>% .$ID
以这种方式定义函数是magrittr链的一个特征。
如果要将一系列查询作为参数传递:
getIDs <- function(...){
DF %>% filter_(...) %>% .$ID
}
getIDs("Gender == 'male'", "Age > 30")
# [1] 100
如果您希望按其中一个参数对结果进行排序,请在dplyr pipline中添加arrange
:
getIDs <- function(..., by = NULL){
DF %>% filter_(...) %>% { if (!is.null(by)) arrange_(., by) else . } %>% .$ID
}
getIDs("Gender == 'female'", "Age > 10", by = "Age")
# [1] 104 101 102
# descending order:
getIDs("Gender == 'female'", "Age > 10", by = "desc(Age)")
# [1] 102 101 104