【问题标题】:Compute difference between columns and save results in a new one using dplyr使用 dplyr 计算列之间的差异并将结果保存在新的列中
【发布时间】:2015-12-09 03:41:55
【问题描述】:

我正在处理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 的新列。

由于我的真实数据框中的列数,我尝试了不同的解决方案。一种解决方案是逐个计算,但不是最优的。此外,我尝试使用 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")

感谢您的帮助!

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    无需转置或使用任何矢量化函数。

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

    【讨论】:

      【解决方案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
      

      【讨论】:

        【解决方案3】:

        这行得通:

            ## 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 的回答也有效。我想我会留在这里,因为它略有不同。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-01-02
          • 1970-01-01
          • 2019-07-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-02-21
          相关资源
          最近更新 更多