使用dplyr计算列之间的差异并将结果保存到新的列中

时间:2015-12-09 03:41:55

标签: r dplyr

我正在处理R中的一些数据。我的数据框DF看起来像这样(我在最后一面添加dput()版本):

    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的新列。

由于我的实际数据帧中的列数,我尝试了不同的解决方案。一种解决方案是逐个计算但不是最优的。此外,我尝试使用mutate_each()包中的dplyr函数,但我不知道如何设置成对列,然后创建新列。此外,我尝试使用同一个包中的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()的{​​{1}}版本是下一个:

DF

感谢您的帮助!

3 个答案:

答案 0 :(得分:3)

无需转置或使用任何矢量化功能。

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

答案 1 :(得分: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

答案 2 :(得分: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的答案也有效。我想我会离开我的,因为它略有不同。