разбить данные на каждый уровень и применить к нему функцию

У меня есть следующий набор данных:

name1 <- c("P1", "P2", "IndA", "IndB", "IndC", "IndD", "IndE", "IndF", "IndG")
name2 <- c("P1", "P2", "IndH", "IndI", "IndJ", "IndK")
name3 <- c("P1", "P2", "IndL", "IndM", "IndN")
name <- c(name1, name2, name3)

A <- c(1, 3, 1, 2, 2, 5, 5, 1, 4, 1, 3, 3, 1, 4, 3, 1, 1, 3,2,1 )
B <- c(2, 4, 3, 4, 2, 2, 6, 2, 2, 1, 4, 3, 1, 1, 5, 2,2, 1, 2, 1 )
family  = c(rep(1, length (name1)), rep(2, length (name2)), rep(3, length (name3)))
mydf <- data.frame (family, name, A, B)

Ниже приведен процесс, который я хочу применить для каждого уровня семейной переменной:

dum.match<-rbind(expand.grid(c(mydf[1,3:4]),c(mydf[2,3:4])),
        expand.grid(c(mydf[2,3:4]),  c(mydf  [1,3:4])))
    newmydf<-cbind(mydf, correct = paste(mydf$A,mydf$B)%in%paste(dum.match$Var1,
        dum.match$Var2))

Итак, я сгенерировал функцию:

err.chk <- function (x) {
    dum.match<-rbind(expand.grid(c(x[1,3:4]),c(x[2,3:4])),
     expand.grid(c(x[2,3:4]),c(x[1,3:4])))
    newmydf<-cbind(x, correct = paste(x$A,mydf$B)%in%paste(dum.match$Var1,
     dum.match$Var2))
    return (newmydf)
    }

Теперь я хочу создать отдельный набор данных 3 для каждого уровня семьи и применить вышеуказанную функцию и объединить результаты в вышеуказанный фрейм данных с правильным дополнительным столбцом. Как мне это сделать ? Я пробовал следовать (и результаты впечатляют!)

 require(plyr) 
 aaply(mydf, 1, err.chk)

Изменить:

Ожидаемый результат:

family name A B  correct 
1       1   P1 1 2  FALSE
2       1   P2 3 4  FALSE
3       1 IndA 1 3  TRUE
4       1 IndB 2 4  TRUE
5       1 IndC 2 2  FALSE
6       1 IndD 5 2  FALSE
7       1 IndE 5 6  FALSE
8       1 IndF 1 2  FALSE
9       1 IndG 4 2  TRUE

10      2   P1 1 1  FALSE
11      2   P2 3 4  FALSE
12      2 IndH 3 3  FALSE
13      2 IndI 1 1  FALSE
14      2 IndJ 4 1  TRUE
15      2 IndK 3 5  FALSE 


16      3   P1 1 2  TRUE
17      3   P2 1 2  TRUE
18      3 IndL 3 1  FALSE
19      3 IndM 2 2  TRUE
20      3 IndN 1 1  TRUE

Только для семьи = 3 (аналогично для других наборов данных)

    # just data for family 3
    name <- c("P1", "P2", "IndL", "IndM", "IndN")
    A <- c(1, 1, 3,2,1 )
    B <- c(2,2, 1, 2, 1)
    mydf <- data.frame (name, A, B)
    err.chk(fam3)

   name A B correct
16   P1 1 2    TRUE
17   P2 1 2    TRUE
18 IndL 3 1   FALSE
19 IndM 2 2    TRUE
20 IndN 1 1    TRUE

person jon    schedule 14.06.2012    source источник
comment
Если вы запустите код, указанный в первом блоке перед функцией, его вывод не будет соответствовать ожидаемому результату. Строка 4 — это FALSE, если вы используете только df[df$family==1,] во всех ваших вызовах mydf. Попробуйте работать с подмножеством ваших данных (т. е. только с одним семейством), пока ваша функция не заработает так, как вы ожидаете. Тогда ddply — ваш ответ.   -  person Justin    schedule 14.06.2012
comment
@sorry justin, mybad ... Я ошибся с индексами 2: 3, их следует заменить на 3: 4, я не заметил, что добавлен семейный столбец ... теперь результаты хорошие, и я принял ваш ответ.   -  person jon    schedule 14.06.2012
comment
не волнуйтесь. Вы всегда можете избежать жестко закодированных индексов столбцов, покупающих имена. expand.grid(x[1, c('A', 'B')], x[2, c('A', 'B')])   -  person Justin    schedule 14.06.2012


Ответы (1)


Трудно точно следовать тому, что вы делаете, но с plyr вы хотите использовать функцию **ply, которая принимает тип данных, который вы ей даете, и возвращает тип данных, возвращаемый вашей функцией. В этом случае ddply выглядит правильным выбором.

Если вы исправите свою функцию в 3-й строке, у вас будет mydf$B, который должен быть x$B:

err.chk <- function (x) {
  dum.match <- rbind(expand.grid(c(x[1, 2:3]), c(x[2, 2:3])),
                     expand.grid(c(x[2, 2:3]), c(x[1, 2:3])))
  newmydf <- cbind(x, correct = paste(x$A, x$B) %in% paste(dum.match$Var1, dum.match$Var2))

  return (newmydf)
}

Вызов с использованием ddply дает разумный результат.

> ddply(mydf, .(family), err.chk)
   family name A B correct
1       1   P1 1 2   FALSE
2       1   P2 3 4   FALSE
3       1 IndA 1 3    TRUE
4       1 IndB 2 4    TRUE
5       1 IndC 2 2   FALSE
6       1 IndD 5 2   FALSE
7       1 IndE 5 6   FALSE
8       1 IndF 1 2   FALSE
9       1 IndG 4 2    TRUE
10      2   P1 1 1   FALSE
11      2   P2 3 4   FALSE
12      2 IndH 3 3   FALSE
13      2 IndI 1 1   FALSE
14      2 IndJ 4 1    TRUE
15      2 IndK 3 5   FALSE
16      3   P1 1 2    TRUE
17      3   P2 1 2    TRUE
18      3 IndL 3 1   FALSE
19      3 IndM 2 2    TRUE
20      3 IndN 1 1    TRUE
person Justin    schedule 14.06.2012
comment
извините, мой плохой ... я неправильные индексы 2: 3 должны быть заменены на 3: 4, я не заметил, что добавлен семейный столбец ... теперь результаты хорошие, и я принял ваш ответ - person jon; 14.06.2012