2013-04-25 61 views
18

這裏計算行之間的區別是我的問題的一個簡單的例子:[R我怎麼能在一個數據幀

> df <- data.frame(ID=1:10,Score=4*10:1) 
> df 
     ID Score 
    1 1 40 
    2 2 36 
    3 3 32 
    4 4 28 
    5 5 24 
    6 6 20 
    7 7 16 
    8 8 12 
    9 9  8 
    10 10  4 
    > diff(df) 

Error in r[i1] - r[-length(r):-(length(r) - lag + 1L)] : 
    non-numeric argument to binary operator 

誰能爲什麼這個錯誤時告訴我嗎?

回答

19

也許你正在尋找的東西是這樣的:

> tail(df, -1) - head(df, -1) 
    ID Score 
2 1 -4 
3 1 -4 
4 1 -4 
5 1 -4 
6 1 -4 
7 1 -4 
8 1 -4 
9 1 -4 
10 1 -4 

您可以減去或添加兩個data.frameš在一起,如果他們是相同的尺寸。因此,我們在這裏做的是將第一行(tail(df, -1))缺失的一個data.frame和缺少最後一行(head(df, -1))的一個減去一個data.frame並減去它們。

+1

+1正面和尾巴的好手法。 – 2013-04-25 10:30:23

+0

+1富有想象力。我永遠不會認爲'-1'的頭會返回除第一行之外的所有內容。聰明 – 2013-04-25 10:36:54

25

diff想要一個矩陣或向量而不是數據框。嘗試

data.frame(diff(as.matrix(df))) 
+0

+1不錯 - 我想這是有道理的,因爲矩陣只是一個具有第二個dim屬性的向量。 – 2013-04-25 10:20:53

+0

+1。到目前爲止,這將是最快的解決方案。 – A5C1D2H2I1M1N2O1R2T1 2013-04-25 10:29:22

+1

僅供參考,1000000行5列數據集中的某些[基準](http://rpubs.com/mrdwab/bmft)。 – A5C1D2H2I1M1N2O1R2T1 2013-04-25 11:30:35

8

因爲df適用於矢量或矩陣。您可以使用適用於跨列應用功能,像這樣:

apply(df , 2 , diff) 
    ID Score 
2 1 -4 
3 1 -4 
4 1 -4 
5 1 -4 
6 1 -4 
7 1 -4 
8 1 -4 
9 1 -4 
10 1 -4 

這似乎不大可能,要計算在順序編號的區別,所以你可以選擇它適用於所有列除了第一像所以:

apply(df[-1] , 2 , diff) 

或者你可以使用data.table(不,它增加任何東西在這裏我真的要開始使用它!),而我又假設你不想申請diff的ID列:

DT <- data.table(df) 
DT[ , list(ID,Score,Diff=diff(Score)) ] 
    ID Score Diff 
1: 1 40 -4 
2: 2 36 -4 
3: 3 32 -4 
4: 4 28 -4 
5: 5 24 -4 
6: 6 20 -4 
7: 7 16 -4 
8: 8 12 -4 
9: 9  8 -4 
10: 10  4 -4 

並感謝@AnandaMahto替代語法,讓更多的靈活選擇其列上運行它可能是:

DT[, lapply(.SD, diff), .SDcols = 1:2] 

這裏.SDcols = 1:2意味着你要在diff功能適用於1和2列。如果你有20列,並且不想將它應用到ID,你可以使用.SDcols=2:20作爲例子。

+0

+1進行編輯。這會讓未來的訪問者對這個問題變得更加困惑。 – A5C1D2H2I1M1N2O1R2T1 2013-04-25 10:55:57

3

我想展示一種替代方式來做這樣的事情,即使我經常感到它不被讚賞這樣做:使用sql。

sqldf(paste("SELECT a.ID,a.Score" 
      ,"  , a.Score - (SELECT b.Score" 
      ,"     FROM df b" 
      ,"     WHERE b.ID < a.ID" 
      ,"     ORDER BY b.ID DESC" 
      ,"     ) diff" 
      ," FROM df a" 
      ) 
    ) 

的代碼看起來很複雜,但它不是,它有一定的優勢,因爲你可以在結果中看到:

ID Score diff 
1 1 40 <NA> 
2 2 36 -4.0 
3 3 32 -4.0 
4 4 28 -4.0 
5 5 24 -4.0 
6 6 20 -4.0 
7 7 16 -4.0 
8 8 12 -4.0 
9 9  8 -4.0 
10 10  4 -4.0 

一個優點是,您使用原始數據框(不轉換成其他類),你會得到一個數據框(把它放在res < - ....)。另一個好處是你還有所有的行。第三個優點是您可以輕鬆考慮分組因素。例如:

df2 <- data.frame(ID=1:10,grp=rep(c("v","w"), each=5),Score=4*10:1) 

sqldf(paste("SELECT a.ID,a.grp,a.Score" 
      ,"  , a.Score - (SELECT b.Score" 
      ,"     FROM df2 b" 
      ,"     WHERE b.ID < a.ID" 
      ,"       AND a.grp = b.grp" 
      ,"     ORDER BY b.ID DESC" 
      ,"     ) diff" 
    ," FROM df2 a" 
    ) 
) 


    ID grp Score diff 
1 1 v 40 <NA> 
2 2 v 36 -4.0 
3 3 v 32 -4.0 
4 4 v 28 -4.0 
5 5 v 24 -4.0 
6 6 w 20 <NA> 
7 7 w 16 -4.0 
8 8 w 12 -4.0 
9 9 w  8 -4.0 
10 10 w  4 -4.0 
4

爲completeness-你可以使用一個簡單的[.data.frame subseting以達到增加這個數年後這太

df[-1, ] - df[-nrow(df), ] 
# ID Score 
# 2 1 -4 
# 3 1 -4 
# 4 1 -4 
# 5 1 -4 
# 6 1 -4 
# 7 1 -4 
# 8 1 -4 
# 9 1 -4 
# 10 1 -4 
+0

您已經發布。所以,你可以添加那些 – akrun 2016-08-05 08:32:00

+0

@akrun,你在那裏有一些不錯的東西.dplyr會長期爲你帶來很多upvotes - 保證。請發佈 – 2016-08-05 08:35:00

+0

好吧,那麼,雖然它違反了我的原則:-) – akrun 2016-08-05 08:35:57

4

使用dplyr另一種選擇是使用通過mutate_each循環所有列,獲得列(.)與列lag.)的差異併除去頂部的NA元素na.omit()

library(dplyr) 
df %>% 
    mutate_each(funs(. - lag(.))) %>% 
    na.omit() 

或者與shiftdata.table。將'data.frame'轉換爲'data.table'(setDT(df)),遍歷列(lapply(.SD, ..) and get the difference between the column ( x ) and the lag ( shift by default gives the lag as type =「lag」`)。刪除第一個觀察,即NA元素。

library(data.table) 
setDT(df)[, lapply(.SD, function(x) (x- shift(x))[-1])]