我想向函数提交一个数据框,并使用它来对另一个数据框进行子集化。
这是基本数据框:
foo <- data.frame(var1= c(1, 1, 1, 2, 2, 3), var2=c('A', 'A', 'B', 'B', 'C', 'C'))
我使用以下函数查找var2
的指定值var1
的频率。
foobar <- function(x, y, z){
a <- subset(x, (x$var1 == y))
b <- subset(a, (a$var2 == z))
n=nrow(b)
return(n)
}
示例:
foobar(foo, 1, "A") # returns 2
foobar(foo, 1, "B") # returns 1
foobar(foo, 3, "C") # returns 1
这很有效。但现在我想向foobar
提交值的数据框。我希望将df
提交给foobar
,而不是上述示例,并获得与上述相同的结果(2,1,1)
df <- data.frame(var1=c(1, 1, 3), var2=c("A", "B", "C"))
当我更改foobar
以接受foobar(foo, df)
这两个参数并使用y[, c(var1)]
和y[, c(var2)]
而不是x
和y
两个参数时它仍然无法正常工作。哪种方式可以做到这一点?
edit1:最后一段澄清
edit2: var1类型已更正
答案 0 :(得分:2)
试试这个:
library(plyr)
match_df <- function(x, match) {
vars <- names(match)
# Create unique id for each row
x_id <- id(match[vars])
match_id <- id(x[vars])
# Match identifiers and return subsetted data frame
x[match(x_id, match_id, nomatch = 0), ]
}
match_df(foo, df)
# var1 var2
# 1 1 A
# 3 1 B
# 5 2 C
答案 1 :(得分:0)
你的函数foobar
期待三个参数,你只用foobar(foo, df)
向它提供了两个参数。您可以使用apply
来获得所需内容:
apply(df, 1, function(x) foobar(foo, x[1], x[2]))
并在使用中:
> apply(df, 1, function(x) foobar(foo, x[1], x[2]))
[1] 2 1 1
回复您的修改:
我不完全确定y[, c(var1)]
的意思,但这是试图找出你想要做的事情。
我认为你要做的是:foobar(foo, y = df[, "var1"], z = df[, "var2"])
。
首先,请注意,此处不需要使用c()
,您可以通过将列的名称放在引号中来引用所需的列,或者按引号逐列引用(如上所述)。其次,df[, "var1"]
返回长度为3的列名var1
的所有行:
> length(df[, "var1"])
[1] 3
您定义的函数未设置为处理长度大于1的向量。这就是为什么我们需要迭代数据帧的每一行以获取单个值,处理它,然后转到下一行在data.frame中。这就是apply函数的作用。这相当于说for (i in 1: length(nrow(df))
的某些内容,但却是处理此类问题的更惯用的方法。
最后,您是否有理由将var1
作为一个因素生成?在我看来,将这些作为数字处理可能更有意义。比较:
> str(df)
'data.frame': 3 obs. of 2 variables:
$ var1: Factor w/ 2 levels "1","3": 1 1 2
$ var2: Factor w/ 3 levels "A","B","C": 1 2 3
对战
> df2 <- data.frame(var1=c(1,1,3), var2=c("A", "B", "C"))
> str(df2)
'data.frame': 3 obs. of 2 variables:
$ var1: num 1 1 3
$ var2: Factor w/ 3 levels "A","B","C": 1 2 3
总之 - apply
是您在此之后的功能。您可能希望花一些时间考虑您的数据是数字还是因素,但仍然可以使用apply。
答案 2 :(得分:0)
foobar2 <- function(x, df) {
.dofun <- function(y, z){
a <- subset(x, x$var1==y)
b <- subset(a, a$var2==z)
n <- nrow(b)
return (n)
}
ans <- mapply(.dofun, as.character(df$var1), as.character(df$var2))
names(ans) <- NULL
return(ans)
}