循环遍历数据框并使用列值匹配/填充行

时间:2021-01-16 16:08:43

标签: r dataframe loops match

df1

...other columns...MON TUE WED THU FRI SAT SUN Total
                   8.5 8.5 8.5 8.5 8.5 6.0 0.0 0.0
                   9.0 9.0 9.0 9.0 9.0 6.0 6.0 0.0
                   6.0 7.0 7.0 7.0 7.0 5.0 0.0 0.0
                   ...about 1400 records/rows of data in df1

df2

Day Hours
FRI   0
SAT   0
SUN   0
MON   0
TUE   0
WED   0
THU   0
FRI   0
SAT   0
SUN   0
MON   0
TUE   0
WED   0
...Will keep going until end (28-31 days worth will be listed - all days in a month)

第一步

我需要遍历 df2 中的所有行,将“Day”列中的所有记录与 df1 列 MON-SUN 匹配...将 df1 中相应的小时数添加到 df2 中的“Hours”列中...仅使用df1 中的第一行,直到所有 df2 都已循环并填充...下面的输出示例

df2 输出

Day   Hours
FRI   8.5
SAT   6.0
SUN   0
MON   8.5
TUE   8.5
WED   8.5
THU   8.5
FRI   8.5
SAT   6.0
SUN   0
MON   8.5
TUE   8.5
WED   8.5
...will continue all the way until last row until all data is filled from 1st row in df1 (repeating itself, just matching the right values)

第二步

在循环并填充 df2 之后 - 然后将 df2 中的“Hours”列的总和放入 df1 的“total”列中

df1 输出

...other columns...MON TUE WED THU FRI SAT SUN Total
                   8.5 8.5 8.5 8.5 8.5 6.0 0.0 88.5
                   9.0 9.0 9.0 9.0 9.0 6.0 6.0
                   6.0 7.0 7.0 7.0 7.0 5.0 0.0

然后重复直到 df1 中的所有行都被循环并经历了相同的过程......所以可能需要某种类型的双循环和匹配函数。我正在努力寻找任何解决方案

使用的代码

row_df1 <- 1
row_df2 <- 1

for (row_df2 in seq(1,nrow(Calendar$Jan))) {
 for (day in week) {
  if (Calendar$Jan[row_df2, 'Day'] == day) {
   Calendar$Jan[row_df2,'Hours'] <- Calctable[row_df1,day]
   row_df2 <- row_df2 + 1
    }
  }
 }

错误信息

 Error in for (day in week) { : invalid for() loop sequence

非常感谢

1 个答案:

答案 0 :(得分:2)

library(dplyr)

df1 <- data.frame(
  MON = c(1,2,3),
  TUE = c(5,6,7),
  WED = c(8,9,10),
  THU = c(11,12,13),
  FRI = c(14,15,16),
  SAT = c(17,18,19),
  SUN = c(20,21,22))

df2 <- data.frame(
  Day = c('THU', 'FRI', 'SAT', 'SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'),
  Hours = 0
)

示例df1:(抱歉,我没有花时间为您重新创建确切的数据,请继续)

    MON   TUE   WED   THU   FRI   SAT   SUN
  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1     1     5     8    11    14    17    20
2     2     6     9    12    15    18    21
3     3     7    10    13    16    19    22

示例df2

   Day   Hours
   <chr> <dbl>
 1 THU       0
 2 FRI       0
 3 SAT       0
 4 SUN       0
 5 MON       0
 6 TUE       0
 7 WED       0
 8 THU       0
 9 FRI       0
10 SAT       0
11 SUN       0
12 MON       0
13 TUE       0
14 WED       0
15 THU       0
16 FRI       0
17 SAT       0
18 SUN       0

第 1 步:这应该是您正在寻找的按照您描述的方式将 df2 排序为 df1 的算法。

row_df2 <- 1

for (row_df1 in seq(1,nrow(df1))) {
  for (day in c('MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'))
    if (df2[row_df2, 'Day'] == day) {
      df2[row_df2,'Hours'] <- df1[row_df1,day]
      row_df2 <- row_df2 + 1
    }
}

第 2 步:现在您可以总结 df1 中的值,例如使用 dplyr

df1 <- df1 %>%
  mutate(
    Sum = MON + TUE + WED + THU + FRI + SAT + SUN
  )

df1:

# A tibble: 3 x 8
    MON   TUE   WED   THU   FRI   SAT   SUN   Sum
  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1     1     5     8    11    14    17    20    76
2     2     6     9    12    15    18    21    83
3     3     7    10    13    16    19    22    90

df2:

# A tibble: 18 x 2
   Day   Hours
   <chr> <dbl>
 1 THU      11 <- row 1: THU
 2 FRI      14 <- row 1: FRI
 3 SAT      17 <- ...
 4 SUN      20
 5 MON       2 <- row 2: MON
 6 TUE       6 <- ....
 7 WED       9
 8 THU      12
 9 FRI      15
10 SAT      18
11 SUN      21 <- row 2: SUN
12 MON       3 <- row 3: MON
13 TUE       7
14 WED      10
15 THU      13
16 FRI      16
17 SAT      19
18 SUN      22

两个表中都没有像 Date 这样的标识符吗?这将使它更加健壮。然后,您可以按日期进行匹配,而无需依赖正确的日期开始。

编辑 1:在测试和删除一些错误后更新。

编辑 2:突出显示来自 df1 的哪个值将落在 df2。我只是使用了与您不同的示例数据(我不想全部输入)。

编辑 3:在示例数据中使用 data.frame 而不是 tibble 来证明它也应该可以工作。

编辑 4:这是您想要的吗?

row_df1 <- 1
row_df2 <- 1

for (row_df2 in seq(1,nrow(df2))) {
  for (day in week) {
    if (df2[row_df2, 'Day'] == day) {
      df2[row_df2,'Hours'] <- df1[row_df1,day]
      row_df2 <- row_df2 + 1
    }
}

df2

将导致:

   Day Hours
1  THU    11 <- row 1: THU
2  FRI    14
3  SAT    17
4  SUN    20
5  MON     1
6  TUE     5
7  WED     8
8  THU    11 <- row 1: THU
9  FRI    14
10 SAT    17
11 SUN    20
12 MON     1
13 TUE     5
14 WED     8
15 THU    11 <- row 1: THU
16 FRI    14
17 SAT    17
18 SUN    20

编辑 5: 似乎缺少 {

for (row_df2 in seq(1,nrow(Calendar$Jan))) {
 for (day in week) {                                       # <- HERE
  if (Calendar$Jan[row_df2, 'Day'] == day) {
   Calendar$Jan[row_df2,'Hours'] <- Calctable[row_df1,day]
   row_df2 <- row_df2 + 1
    }
  }

编辑 6:

在 Edit 5 中,我分配了 week <- c('MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN') 但忘记提及它。它应该看起来像(这里没有特殊的内置变量):

week <- c('MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN')

for (row_df2 in seq(1,nrow(Calendar$Jan))) {
 for (day in week) {
  if (Calendar$Jan[row_df2, 'Day'] == day) {
   Calendar$Jan[row_df2,'Hours'] <- Calctable[row_df1,day]
   row_df2 <- row_df2 + 1
  }
 }
}

以防您在代码中的其他地方重用 week。我用它来测试循环并在此答案的先前版本中混合使用。