使用另一个数据帧作为参数来子集函数中的数据帧

时间:2011-01-14 17:13:08

标签: function r dataframe

我想向函数提交一个数据框,并使用它来对另一个数据框进行子集化。

这是基本数据框:

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)]而不是xy两个参数时它仍然无法正常工作。哪种方式可以做到这一点?

edit1:最后一段澄清

edit2: var1类型已更正

3 个答案:

答案 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)
}