2015-12-09 48 views
3

我正在使用R中的一些數據。我的數據框DF看起來像這樣(我加在最後面的dput()版本):使用dplyr計算列之間的差異並將結果保存爲新結果

ID S.2014.01.01 S.2014.01.02 S.2014.01.03 S.2014.01.04 
1 001   1   10   5   74 
2 002   2   15   6   75 
3 003   3   23   7   76 
4 004   4   31   8   77 
5 005   5   39   9   78 
6 006   6   47   10   79 
7 007   7   55   11   80 
8 008   8   63   12   81 
9 009   9   71   13   82 
10 010   10   79   14   83 

DF包含一個ID變量,並通過天解釋值(在這個例子中,我只包括4個變量多列,真正的數據幀這種風格有超過100個變量)。我的目標是計算每對變量之間的差異。例如,我想計算變量S.2014.01.02S.2014.01.01之間的差異,然後將這些值保存在名爲D.2014.01.02的新變量中。下一個變量的過程是一樣的。下一個案例是S.2014.01.03S.2014.01.02,然後創建一個名爲D.2014.01.03的新列。

由於我真實數據框中的列數,我嘗試了不同的解決方案。一種解決方案是逐個計算,但不是最優的。另外,我嘗試使用dplyr包中的mutate_each()函數,但我不知道如何設置成對列,然後創建新列。此外,我已經嘗試使用相同包中的lag()函數,但它不起作用。我之所以使用這個函數是因爲我可能需要計算不同列的差異,但也可能需要兩個或三個列之間的差異,而不是一個(對)。我想獲得一個數據幀是這樣的:

ID S.2014.01.01 S.2014.01.02 S.2014.01.03 S.2014.01.04 D.2014.01.02 D.2014.01.03 D.2014.01.04 
1 001   1   10   5   74   9   -5   69 
2 002   2   15   6   75   13   -9   69 
3 003   3   23   7   76   20   -16   69 
4 004   4   31   8   77   27   -23   69 
5 005   5   39   9   78   34   -30   69 
6 006   6   47   10   79   41   -37   69 
7 007   7   55   11   80   48   -44   69 
8 008   8   63   12   81   55   -51   69 
9 009   9   71   13   82   62   -58   69 
10 010   10   79   14   83   69   -65   69 

在這個數據框,我們可以看出,隨着D啓動新的變量和他們對列的差異的結果。如果你可以給出一些關於這種情況的建議,那麼有兩個變量會很棒,但是如果你可以幫助我使用一個差異版本,那麼每個2或3列都是非常棒的。該dput()版本的DF是下一個:

DF<-structure(list(ID = c("001", "002", "003", "004", "005", "006", 
"007", "008", "009", "010"), S.2014.01.01 = c(1, 2, 3, 4, 5, 
6, 7, 8, 9, 10), S.2014.01.02 = c(10, 15, 23, 31, 39, 47, 55, 
63, 71, 79), S.2014.01.03 = c(5, 6, 7, 8, 9, 10, 11, 12, 13, 
14), S.2014.01.04 = c(74, 75, 76, 77, 78, 79, 80, 81, 82, 83)), .Names = c("ID", 
"S.2014.01.01", "S.2014.01.02", "S.2014.01.03", "S.2014.01.04" 
), row.names = c(NA, -10L), class = "data.frame") 

感謝您的幫助!

回答

2

我用基本功能做了以下工作。首先,我刪除了ID列並創建了一個臨時數據框。使用它,我拿了兩列,並在sapply()處理減法。將結果轉換爲數據框並使用gsub()分配新列名稱。最後,我結合了原始數據,DF,並將結果(即新)與cbind()

### Remove ID column 
temp <- DF[, -1] 

### pick up two columns and handle subtraction 

new <- data.frame(sapply(1:(length(names(temp))-1), function(x){ 
        temp[, x+1] - temp[ , x] 
       })) 

### Assign column names. Change S to D in the word initial position and remove 
### the first element of the vector. 

names(new) <- gsub(pattern = "^[A-Z]", replacement = "D", x = names(temp))[-1L] 

### Combine the original DF and the results 

cbind(DF, new) 


    ID S.2014.01.01 S.2014.01.02 S.2014.01.03 S.2014.01.04 D.2014.01.02 D.2014.01.03 D.2014.01.04 
1 001   1   10   5   74   9   -5   69 
2 002   2   15   6   75   13   -9   69 
3 003   3   23   7   76   20   -16   69 
4 004   4   31   8   77   27   -23   69 
5 005   5   39   9   78   34   -30   69 
6 006   6   47   10   79   41   -37   69 
7 007   7   55   11   80   48   -44   69 
8 008   8   63   12   81   55   -51   69 
9 009   9   71   13   82   62   -58   69 
10 010   10   79   14   83   69   -65   69 
1

這工作:

## apply will return data we want in rows, to transpose with t() ---- 
    newDF <- t(apply(DF[,-1], 1, function(x){ diff(x) })) 
    newDF <- data.frame(newDF) 
    ## set names we want 
    names(newDF) <- gsub(names(DF[,-c(1:2)]), pattern = "S.", replacement = "D.") 
    ## combine into 1 data frame 
    newDF <- cbind(DF, newDF) 
    newDF 
    ID S.2014.01.01 S.2014.01.02 S.2014.01.03 S.2014.01.04 D.2014.01.02 D.2014.01.03 D.2014.01.04 
1 001   1   10   5   74   9   -5   69 
2 002   2   15   6   75   13   -9   69 
3 003   3   23   7   76   20   -16   69 
4 004   4   31   8   77   27   -23   69 
5 005   5   39   9   78   34   -30   69 
6 006   6   47   10   79   41   -37   69 
7 007   7   55   11   80   48   -44   69 
8 008   8   63   12   81   55   -51   69 
9 009   9   71   13   82   62   -58   69 
10 010   10   79   14   83   69   -65   69 

注意,我只看到了@ jazzurro的答案,作品也。我想我會離開這裏,因爲它是略微不同。

1

不需要轉置或使用任何矢量化函數。

DF <- cbind(DF, DF[,3:5] - DF[,2:4]) 
names(DF)[6: 8] = gsub("S", "D", names(DF)[6: 8]) 
相關問題