2013-02-12 5 views
5

У меня есть небольшой вопрос о применении функций. Например, у меня есть:Как разбить список data.frame и применить функцию к одному столбцу?

l <- list(a = data.frame(A1=rep(10,5),B1=c(1,1,1,2,2),C1=c(5,10,20,7,30)), 
      b = data.frame(A1=rep(20,5),B1=c(3,3,4,4,4),C1=c(3,5,10,20,30))) 

Я хочу найти минимальный C1 для каждого B1. Результат должен быть

$a 
    A1 B1 C1 
    10 1 5 
    10 2 7 

$b 
    A1 B1 C1 
    20 3 3 
    20 4 10 

Я знаю, как сделать это с «за», но он должен быть более простой способ с «lapply», но я не мог сделать это работает.

Пожалуйста, помогите

ответ

2

Вот еще один подход, который соответствует вашему желаемому результату:

lapply(l, function(x) { 
    temp <- ave(x[["C1"]], x["B1"], FUN = min) 
    x[x[["C1"]] == temp, ] 
}) 
# $a 
# A1 B1 C1 
# 1 10 1 5 
# 4 10 2 7 
# 
# $b 
# A1 B1 C1 
# 1 20 3 3 
# 3 20 4 10 
+0

Это именно то, что я хотел, большое спасибо. Я не знал такого использования ave – Tali

3

насчет объединения lapply и tapply:

lapply(l, function(i) tapply(i$C1, i$B1, min)) 
$a 
1 2 
5 7 

$b 
3 4 
3 10 

Хитрость думать о нескольких операциях, чтобы разбить задачу на куски. SO,

  1. Минимальное C1 для каждого B1. Как мы это сделаем для одного кадра?

    i = l[[1]] 
    tapply(i$C1, i$B1, min) 
    
  2. Каждый элемент списка? Просто используйте lapply:

    lapply(l, function(i) tapply(i$C1, i$B1, min)) 
    

Если вы не можете сделать шаг 1, вы не будете иметь возможности управлять шаг 2.

+0

Большое спасибо – Tali

0

Вы также можете попробовать llply + dcast из plyr/reshape2 инструментов:

library(reshape2) 
library(plyr) 

    l <- list(a = data.frame(A1=rep(10,5),B1=c(1,1,1,2,2),C1=c(5,10,20,7,30)), 
       b = data.frame(A1=rep(20,5),B1=c(3,3,4,4,4),C1=c(3,5,10,20,30))) 

    llply(l, function (x) {dcast (x, A1+B1~., value.var="C1", min)}) 
3

Недавно поддался сирены песню data.table пакета и его сочетание гибкости и скорости для ведения операций, как это, я представить еще одно решение:

library(data.table) 
lapply(l, function(dat) { 
    data.table(dat, key="B1,C1")[list(unique(B1)), mult="first"] 
}) 

Если сохранить исходный порядок столбцов имеет важное значение, для по какой-то причине звонок data.table() может быть обернут setcolorder(..., names(dat)).