【问题标题】:Iterate over data frame for calculation遍历数据框进行计算
【发布时间】:2022-01-12 21:04:47
【问题描述】:

我有一个包含两行的数据框,分别代表上车和下车的乘客:

    A  B  C  D  E  F
In  9  10 6  9  14 10
Out 0  1  2  3  4  3

并且我想做一个计算,将产生另外两行信息,其中第一行是到达车站 A/B/C/等时在公共汽车上的乘客,第 2 行是在那个车站下车的乘客。

第 1 行的数字应该与第 2 行的前一个数字相同,例如 B 站的第 2 行是 `9(从上一站出发的公交车上的剩余人数)+ BIn (在车站上车的人数)- BOut(在车站下车的人数)。

最终结果应该是这样的:

    A  B  C  D  E  F
In  9  10 6  9  14 10
Out 0  1  2  3  4  3
1   0  9  18 22 28 38
2   9  18 22 28 38 45

我将如何遍历数据框以便获得这些数字?是否需要一个 for 循环,或者有没有更简单的方法来完成这个计算?

【问题讨论】:

    标签: r dataframe for-loop


    【解决方案1】:

    首先,我认为将它们作为列而不是行更有意义。这样您就可以利用 R 中的矢量化操作。

    library(data.table)
    df <- suppressWarnings(fread('
        A  B  C  D  E  F
    In  9  10 6  9  14 10
    Out 0  1  2  3  4  3'))
    setDT(df) # only required if not starting with a data.table
    df
    #>        V1     A     B     C     D     E     F
    #>    <char> <int> <int> <int> <int> <int> <int>
    #> 1:     In     9    10     6     9    14    10
    #> 2:    Out     0     1     2     3     4     3
    
    df_tp <- transpose(df, make.names = 'V1', keep.names = 'station')
    df_tp
    #>    station    In   Out
    #>     <char> <int> <int>
    #> 1:       A     9     0
    #> 2:       B    10     1
    #> 3:       C     6     2
    #> 4:       D     9     3
    #> 5:       E    14     4
    #> 6:       F    10     3
    
    

    现在您的最后一行是 In 的累积总和减去 Out 的累积总和。另一个只是它的滞后版本。

    df_tp[, net := cumsum(In) - cumsum(Out)]
    df_tp[, lagged_net := shift(net, fill = 0)]
    df_tp
    #>    station    In   Out   net lagged_net
    #>     <char> <int> <int> <int>      <int>
    #> 1:       A     9     0     9          0
    #> 2:       B    10     1    18          9
    #> 3:       C     6     2    22         18
    #> 4:       D     9     3    28         22
    #> 5:       E    14     4    38         28
    #> 6:       F    10     3    45         38
    

    reprex package 创建于 2021-12-07 (v2.0.1)

    【讨论】:

    • 谢谢!我对向量运算不是太熟悉,所以我肯定要搜索其中的一些函数。
    【解决方案2】:

    我认为您应该接受@IceCreamToucan 的建议和回答,但如果您出于特定原因想要保持相同的结构,这个不优雅的蛮力for 循环将产生您想要的输出:

    df <- data.frame(A = c(9,0),
                     B = c(10,1),
                     C = c(6,2),
                     D = c(9,3),
                     E = c(14, 4),
                     F = c(10, 3))
    
    for (i in 1:ncol(df)){
      if (i == 1){df[3:4,1] <- c(0,df[1,1])}
      else{
        df[3,i] <- df[4,i-1]
        df[4,i] <- sum(df[4,i-1], df[1,i]) - df[2,i]
        }
    }
    df
    #  A  B  C  D  E  F
    #1 9 10  6  9 14 10
    #2 0  1  2  3  4  3
    #3 0  9 18 22 28 38
    #4 9 18 22 28 38 45
    

    【讨论】:

    • 谢谢!我会看看@IceCreamToucan 的答案(我是向量操作的新手),但如果我想使用 for 循环,这就是我正在寻找的
    • 如何为数据框列表执行此操作?
    • for 循环定义为function(即loopfun &lt;- function(x) { ...code here...},然后使用lapply,类似于lapply(df.lists, loopfun)
    【解决方案3】:

    或者使用tidyverse 的方式来做到这一点:

    以您共享的格式加载数据:
    library(tidyverse)
    
    df <- data.frame(A = c(9,0), 
                     B = c(10,1), 
                     C = c(6,2), 
                     D = c(9,3), 
                     E = c(14,4), 
                     F = c(10,3)) 
    
    > df
      A  B C D  E  F
    1 9 10 6 9 14 10
    2 0  1 2 3  4  3
    
    转换为长格式:
    df <- as_tibble(t(df), rownames = "row_names") %>% 
          rename('In' = V1, 'Out' = V2)
    
    > df
    
    # A tibble: 6 x 3
      row_names    In   Out
      <chr>     <dbl> <dbl>
    1 A             9     0
    2 B            10     1
    3 C             6     2
    4 D             9     3
    5 E            14     4
    6 F            10     3
    
    cumsumlag添加你想要的变量:
    df %>% mutate(net = cumsum(In) - cumsum(Out), 
                  lag = replace_na(lag(net), 0))
    
    > df
    
    # A tibble: 6 x 5
      row_names    In   Out   net   lag
      <chr>     <dbl> <dbl> <dbl> <dbl>
    1 A             9     0     9     0
    2 B            10     1    18     9
    3 C             6     2    22    18
    4 D             9     3    28    22
    5 E            14     4    38    28
    6 F            10     3    45    38
    

    【讨论】:

      猜你喜欢
      • 2021-02-22
      • 2018-09-02
      • 1970-01-01
      • 1970-01-01
      • 2016-06-21
      • 1970-01-01
      • 2020-11-11
      • 2021-07-19
      • 2014-04-21
      相关资源
      最近更新 更多