遍历数据框进行计算

Posted

技术标签:

【中文标题】遍历数据框进行计算【英文标题】: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 循环,或者有没有更简单的方法来完成这个计算?

【问题讨论】:

【参考方案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

【讨论】:

以上是关于遍历数据框进行计算的主要内容,如果未能解决你的问题,请参考以下文章

循环遍历数据框:计算每个唯一变量的值的每个成对组合。

遍历 pyspark 数据框中的列,而不为单个列创建不同的数据框

循环遍历数据框字典中的数据框

在遍历期间更新数据框

计算数据框列中真/假的出现次数

Python:如何从具有多列的数据框中循环遍历每两列组合以进行聚类?