2014-11-18 2 views
0

Я пытаюсь рассчитать рост диаметра набора деревьев в течение нескольких лет в кадре данных, в котором каждая строка является данным деревом в течение данного года. Как правило, такие данные имеют каждый отдельный стержень в виде одной строки с диаметром этого ствола для каждого года, указанным в отдельной колонке, но по разным причинам этот информационный кадр должен оставаться таким, чтобы каждый ряд был отдельным стержнем в течение одного года. Упрощенная версия модели данных будет выглядеть следующим образомРасчет роста дерева с использованием цикла

df<-data.frame("Stem"=c(1:5,1:5,1,2,3,5,1,2,3,5,6), 
      "Year"=c(rep(1997,5), rep(1998,5), rep(1999,4), rep(2000,5)), 
      "Diameter"=c(1:5,seq(1.5,5.5,1),2,3,4,6,3,5,7,9,15)) 
df 
    Stem Year DAP 
1  1 1997 1.0 
2  2 1997 2.0 
3  3 1997 3.0 
4  4 1997 4.0 
5  5 1997 5.0 
6  1 1998 1.5 
7  2 1998 2.5 
8  3 1998 3.5 
9  4 1998 4.5 
10 5 1998 5.5 
11 1 1999 2.0 
12 2 1999 3.0 
13 3 1999 4.0 
14 5 1999 6.0 
15 1 2000 3.0 
16 2 2000 5.0 
17 3 2000 7.0 
18 5 2000 9.0 
19 6 2000 15.0 

То, что я пытаюсь сделать это, чтобы сделать новый столбец, который принимает диаметр для данного ствола в данном году, и вычитает диаметр для того же ствола в прошлом году. Я предполагаю, что для этого потребуется некоторый набор вложенных циклов. Что-то вроде

for (i in 1:length(unique(df$Stem_ID){ 
    for (t in 2:length(unique(df$Year){ 
..... 
    } 
} 

Что я борюсь с как написать функцию, которая вычисляет: Диаметр [т] -Диаметр [т-1] для каждого ствола. Любые предложения будут ценны.

ответ

0

Try:

> do.call(rbind, lapply(split(df, df$Stem), function(x) transform(x, diff = c(0,diff(x$Diameter))))) 
    Stem Year Diameter diff 
1.1  1 1997  1.0 0.0 
1.6  1 1998  1.5 0.5 
1.11 1 1999  2.0 0.5 
1.15 1 2000  3.0 1.0 
2.2  2 1997  2.0 0.0 
2.7  2 1998  2.5 0.5 
2.12 2 1999  3.0 0.5 
2.16 2 2000  5.0 2.0 
3.3  3 1997  3.0 0.0 
3.8  3 1998  3.5 0.5 
3.13 3 1999  4.0 0.5 
3.17 3 2000  7.0 3.0 
4.4  4 1997  4.0 0.0 
4.9  4 1998  4.5 0.5 
5.5  5 1997  5.0 0.0 
5.10 5 1998  5.5 0.5 
5.14 5 1999  6.0 0.5 
5.18 5 2000  9.0 3.0 
6  6 2000  15.0 0.0 
+0

Это сделало именно то, что мне было нужно для этого. Это гораздо более элегантный способ сделать это, чем я имел в виду. Спасибо, так много! – Ben

+0

не забудьте принять его ответ, если он вам приемлем! – jed

0

ответ работы Rnso в. Кроме того, можно сделать несколько короче:

>df[order(df$Stem),] 
>df$diff <- unlist(tapply(df$Diameter,df$Stem, function(x) c(NA,diff(x)))) 

    Stem Year Diameter diff 
1  1 1997  1.0 NA 
6  1 1998  1.5 0.5 
11 1 1999  2.0 0.5 
15 1 2000  3.0 1.0 
2  2 1997  2.0 NA 
7  2 1998  2.5 0.5 
12 2 1999  3.0 0.5 
16 2 2000  5.0 2.0 
3  3 1997  3.0 NA 
8  3 1998  3.5 0.5 
13 3 1999  4.0 0.5 
17 3 2000  7.0 3.0 
4  4 1997  4.0 NA 
9  4 1998  4.5 0.5 
5  5 1997  5.0 NA 
10 5 1998  5.5 0.5 
14 5 1999  6.0 0.5 
18 5 2000  9.0 3.0 
19 6 2000  15.0 NA 

Или, если вы готовы использовать data.table пакет, который может быть очень кратким:

>require(data.table) 
>DT <- data.table(df) 
>setkey(DT,Stem) 
>DT <- DT[,diff:= c(NA, diff(Diameter)), by = Stem] 
>df <- as.data.frame(DT) 

    Stem Year Diameter diff 
1  1 1997  1.0 NA 
2  1 1998  1.5 0.5 
3  1 1999  2.0 0.5 
4  1 2000  3.0 1.0 
5  2 1997  2.0 NA 
6  2 1998  2.5 0.5 
7  2 1999  3.0 0.5 
8  2 2000  5.0 2.0 
9  3 1997  3.0 NA 
10 3 1998  3.5 0.5 
11 3 1999  4.0 0.5 
12 3 2000  7.0 3.0 
13 4 1997  4.0 NA 
14 4 1998  4.5 0.5 
15 5 1997  5.0 NA 
16 5 1998  5.5 0.5 
17 5 1999  6.0 0.5 
18 5 2000  9.0 3.0 
19 6 2000  15.0 NA 

Если у вас есть большой набор данных, данные. таблица имеет то преимущество, что она очень быстро.