Подмножество фрейма данных в функции с использованием другого фрейма данных в качестве параметра - PullRequest
2 голосов
/ 14 января 2011

Я хотел бы передать фрейм данных в функцию и использовать его для поднабора другого фрейма данных.

Это базовый фрейм данных:

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

Ответы [ 3 ]

2 голосов
/ 15 января 2011

Попробуйте это:

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
0 голосов
/ 15 января 2011
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)
}
0 голосов
/ 14 января 2011

Ваша функция 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"] возвращает все строки для имен столбцов 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 - это функция, которую вы ищете здесь.Возможно, вы захотите потратить некоторое время на размышления о том, должны ли ваши данные быть числовыми или иметь коэффициент, но применять все равно нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...