Объединить список data.frames с именем элемента списка в качестве фактора в объединенном фрейме данных - PullRequest
2 голосов
/ 27 июля 2011

У меня есть data.frame, как показано ниже, где location - это коэффициент, а sample - это некоторый пример измерения:

  location sample
1      'A'   0.10
2      'A'   0.20
3      'A'   0.15
4      'B'   0.15
5      'B'   0.99
6      'B'   0.54
...

У меня есть функция ECCDFpts(df), где df - это data.frame, который возвращает набор <x,y> точек на эмпирическом CCDF df$sample, например:

    x     y
1 0.0  1.00
2 0.1  0.99
3 0.2  0.75
...

Обратите внимание, что количество <x,y> возвращаемых точек является "произвольным". Существует , а не сопоставление один к одному между входными выборками и выходными <x,y> строками.

Я хотел бы вычислить эти данные CCDF на на фактор (например, местоположение) на основе, получив data.frame, как это:

  location    x    y
1      'A'  0.0  1.0
2      'A'  0.1  1.0
3      'A'  0.2  0.3
4      'B'  0.0  1.0
5      'B'  0.1  1.0
6      'B'  0.2  0.7
...

Мой текущий подход состоит в том, чтобы разделить начальный фрейм данных на коэффициент location:

eccdfs_by_factor <- by(data, data$location, ECCDFpts)

Это дает список data.frames:

data$location: A
    x    y
1 0.0  1.0
2 0.1  1.0
3 0.2  0.3
-----------------
data$location: B
    x    y
1 0.0  1.0
2 0.1  1.0
3 0.2  0.7

Я не знаю, как объединить или разложить это обратно в желаемую форму, показанную ранее. Я хочу объединить так, чтобы имя элементов (data.frames) в списке стало фактором столбца в объединенном data.frame.

Решение:

Это классическая проблема разделения-применения-объединения, по-видимому. Самые чистые решения ниже используют пакетную функцию plyr ddply(...) для разделения, наложения и объединения в одну строку! Нет необходимости в базовой функции by, которую я использовал выше.

Ответы [ 3 ]

4 голосов
/ 27 июля 2011

Обновление: если я правильно понимаю, что вы хотите, чтобы вы правильно ...

library(plyr)
ldply(your_data)

Например:

x <- list(a=data.frame(x=c(1,2,3,4),y=c(2,3,4,5)),
          b=data.frame(x=c(4,3,2,1),y=c(5,4,3,2)))
ldply(x)

  .id x y
1   a 1 2
2   a 2 3
3   a 3 4
4   a 4 5
5   b 4 5
6   b 3 4
7   b 2 3
8   b 1 2
3 голосов
/ 27 июля 2011

Полученных вами ответов более чем достаточно, но для полноты я хотел бы добавить решение, объясняющее, как получить желаемый результат, начиная с вывода команды by.Я собираюсь использовать слегка измененную версию примера Рамната для иллюстрации:

mydata = data.frame(
  location = rep(LETTERS[1:3], each = 3),
  sample   = runif(9)
)

# DEFINE DUMMY FUNCTION - slightly different from ramnath's
myfunc = function(dat){
    temp <- data.frame(x = runif(3), y = rnorm(3))
    return(temp) 
}         

Вы разделяете данные на location и применяете свою функцию, используя by:

rs <- by(mydata,mydata$location,FUN = myfunc)

mydata$location: A
          x           y
1 0.2730105 -0.06923224
2 0.9354096 -0.18336131
3 0.6359926 -0.04054326
----------------------------------------------------------- 
mydata$location: B
          x           y
1 0.5621529 -0.26404739
2 0.8098687  0.07912883
3 0.7334650  0.38287794
----------------------------------------------------------- 
mydata$location: C
          x          y
1 0.8443924 -0.9055125
2 0.7922256  0.1757586
3 0.4923929 -0.1931579

Теперь очень удобно знать, что мы можем снова собрать все вместе, используя do.call и rbind:

result <- do.call(rbind,rs)

            x           y
A.1 0.2730105 -0.06923224
A.2 0.9354096 -0.18336131
A.3 0.6359926 -0.04054326
B.1 0.5621529 -0.26404739
B.2 0.8098687  0.07912883
B.3 0.7334650  0.38287794
C.1 0.8443924 -0.90551251
C.2 0.7922256  0.17575858
C.3 0.4923929 -0.19315789

Но подождите, говорите вы!Как насчет добавления моего столбца местоположения?Обратите внимание, что do.call(rbind,rs) сделал с именами строк вашего результата!Мы можем добавить столбец местоположения, просто извлекая первый символ из имен строк:

result$location <- substr(row.names(result),1,1)

Это, конечно, предполагает, что ваши местоположения закодированы с использованием одного символа.Но в общем случае имена результирующих строк должны иметь форму location.x, чтобы вы всегда могли strsplit или регулярные выражения для извлечения имен местоположений.

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

#Output not shown
myfunc1 = function(dat){
    temp <- data.frame(x = runif(3), y = rnorm(3))
    temp$location <- dat$location[1]
    return(temp) 
}
rs1 <- by(mydata,mydata$location,FUN = myfunc1)
result1 <- do.call(rbind,rs1)

Так что вам просто нужно изменить вашу функцию ECCDFpts аналогичным образом.

3 голосов
/ 27 июля 2011

Одноразовое решение использует пакет plyr. Поскольку я не знаю вашу функцию ECDFpts, я собираюсь написать свою собственную, чтобы проиллюстрировать использование.

# DEFINE DUMMY DATA
mydata = data.frame(
  location = rep(LETTERS[1:3], each = 3),
  sample   = runif(9)
)

# DEFINE DUMMY FUNCTION
myfunc = function(dat){
   x = dat - mean(dat)
   y = dat - median(dat)
   return(data.frame(x, y)) 
}

# USE PLYR TO APPLY FUNCTION BY LOCATION
library(plyr)
ans = ddply(mydata, .(location), transform, x = myfunc(sample)$x, 
         y = myfunc(sample)$y)

  location sample       x      y
1        A  0.911  0.3279  0.232
2        A  0.678  0.0958  0.000
3        A  0.159 -0.4237 -0.520
4        B  0.908  0.3096  0.048
5        B  0.860  0.2615  0.000
6        B  0.027 -0.5711 -0.833
7        C  0.745  0.0694  0.000
8        C  0.343 -0.3327 -0.402
9        C  0.939  0.2633  0.194

EDIT. Как указано в комментариях @David, код можно еще более упростить до

# DEFINE DUMMY FUNCTION
myfunc = function(dat){
   x = with(dat, sample - mean(sample))
   y = with(dat, sample - median(sample))
   return(data.frame(x, y)) 
}

ans = ddply(mydata, .(location), myfunc)

  location       x        y
1        A -0.0308 -0.00564
2        A -0.0251  0.00000
3        A  0.0559  0.08102
4        B -0.4985 -0.69084
5        B  0.3062  0.11392
6        B  0.1923  0.00000
7        C -0.2894 -0.31495
8        C  0.0255  0.00000
9        C  0.2639  0.23838
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...