2013-05-18 5 views
1

У меня есть dataframe, который выглядит следующим образом:вычисления разницы в dataframe

set.seed(50) 
data.frame(distance=c(rep("long", 5), rep("short", 5)), 
      year=rep(2002:2006), 
      mean.length=rnorm(10)) 

    distance year mean.length 
1  long 2002 0.54966989 
2  long 2003 -0.84160374 
3  long 2004 0.03299794 
4  long 2005 0.52414971 
5  long 2006 -1.72760411 
6  short 2002 -0.27786453 
7  short 2003 0.36082844 
8  short 2004 -0.59091244 
9  short 2005 0.97559055 
10 short 2006 -1.44574995 

Мне нужно вычислить разницу между в mean.length между long и short в каждом году. Каков самый быстрый способ сделать это?

ответ

5

Вот один из способов использования plyr:

set.seed(50) 
df <- data.frame(distance=c(rep("long", 5),rep("short", 5)), 
       year=rep(2002:2006), 
       mean.length=rnorm(10)) 

library(plyr) 
aggregation.fn <- function(df) { 
    data.frame(year=df$year[1], 
      diff=(df$mean.length[df$distance == "long"] - 
        df$mean.length[df$distance == "short"]))} 
new.df <- ddply(df, "year", aggregation.fn) 

Дает

> new.df 
    year  diff 
1 2002 0.8275344 
2 2003 -1.2024322 
3 2004 0.6239104 
4 2005 -0.4514408 
5 2006 -0.2818542 

Второй способ

df <- df[order(df$year, df$distance), ] 
n <- dim(df)[1] 
df$new.year <- c(1, df$year[2:n] != df$year[1:(n-1)]) 
df$diff <- c(-diff(df$mean.length), NA) 
df$diff[!df$new.year] <- NA 
new.df.2 <- df[!is.na(df$diff), c("year", "diff")] 

all(new.df.2 == new.df) # True 
+1

Вы можете сохранить некоторую типизацию с помощью 'ddply (df," year ", summary, val = mean.length [distance == 'long'] - mean.length [distance == 'short']), вероятно. – joran

+0

Круто, это тоже работает. Я не знал о суммировании, спасибо :) – Adrian

3

Использование tapply() и apply() так:

apply(
    with(x, tapply(mean.length, list(year, distance), FUN=mean)), 
    1, 
    diff 
) 

     2002  2003  2004  2005  2006 
-0.8275344 1.2024322 -0.6239104 0.4514408 0.2818542 

Это работает, потому что tapply создает табличный резюме по year и distance:

with(x, tapply(mean.length, list(year, distance), FUN=mean)) 

      long  short 
2002 0.54966989 -0.2778645 
2003 -0.84160374 0.3608284 
2004 0.03299794 -0.5909124 
2005 0.52414971 0.9755906 
2006 -1.72760411 -1.4457499 
2

Так как вы, кажется, имеют спаренные значения и data.frame упорядочен, вы можете сделать это:

res <- with(DF, mean.length[distance=="long"]-mean.length[distance=="short"]) 
names(res) <- unique(DF$year) 

#  2002  2003  2004  2005  2006 
#0.8275344 -1.2024322 0.6239104 -0.4514408 -0.2818542 

Это должно быть довольно быстро, но не так безопасно, как другие ответы, поскольку он полагается на предположения.

1

Вы получили хорошие ответы для вычисления конкретного вопроса. Это может иметь смысл для вас рассмотреть возможность изменения ваших данных в широком формате. Вот два варианта:

reshape(df, direction = "wide", idvar = "year", timevar = "distance") 
#--- 
    year mean.length.long mean.length.short 
1 2002  0.54966989  -0.2778645 
2 2003  -0.84160374   0.3608284 
3 2004  0.03299794  -0.5909124 
4 2005  0.52414971   0.9755906 
5 2006  -1.72760411  -1.4457499 

#package reshape2 is probably easier to use. 
library(reshape2) 
dcast(year ~ distance, data = df) 
#--- 
    year  long  short 
1 2002 0.54966989 -0.2778645 
2 2003 -0.84160374 0.3608284 
3 2004 0.03299794 -0.5909124 
4 2005 0.52414971 0.9755906 
5 2006 -1.72760411 -1.4457499 

Вы можете легко вычислить свою новую статистику сейчас.

 Смежные вопросы

  • Нет связанных вопросов^_^