R:如何将数据框列中的NA替换为利用其他多个列的条件值?

时间:2019-10-03 17:19:30

标签: r

我使用R,试图利用其他列的条件值填充一列NA。数据帧有4列。下面介绍这4列。

“ Water_Level”:具有一些值,其中也包括NA。这是我要替换NA的列。将此列作为水箱中以升为单位的水量。

“坦克”:坦克的唯一标识。在此示例中,我有水箱1和水箱2。

“标志”:它具有一系列的0和1。当值为0时,打开水龙头,水位值减小0.05的常数。当flag为1时,将对水箱进行抽水,因此各个水箱中的水位逐渐增加到一系列1结束时的峰值。增加的速率各不相同,并且取决于“标志”列中1的长度或对应于1的序列末尾的计数器编号。

“ Counter”:一列,该列按顺序在flag列中计数0和1的数目。

我需要用其他列的条件填充“水位”列中的NA。

老实说,尽管清楚地了解了所需的结果,但我还是无法尝试任何事情。

df <- data.frame(
  Water_level = c(67.92, rep(NA,9),67.96,10.5,rep(NA,8),20),
  Flag = c(rep(0,5),rep(1,6),rep(0,5),rep(1,5)),
  Tank= c(rep(1, 11), rep(2, 10)),
  Counter = c(seq(1:5),seq(1:6), seq(1:5),seq(1:5))
)

df

   Water_level Flag Tank Counter
1        67.92    0    1       1
2           NA    0    1       2
3           NA    0    1       3
4           NA    0    1       4
5           NA    0    1       5
6           NA    1    1       1
7           NA    1    1       2
8           NA    1    1       3
9           NA    1    1       4
10          NA    1    1       5
11       67.96    1    1       6
12       10.50    0    2       1
13          NA    0    2       2
14          NA    0    2       3
15          NA    0    2       4
16          NA    0    2       5
17          NA    1    2       1
18          NA    1    2       2
19          NA    1    2       3
20          NA    1    2       4
21       20.00    1    2       5

预期结果是按照我的简介中的条件描述,将水位填充到NA中。

例如,“水位”中的第2行应为67.92-0.05 = 67.87。这是因为分接头是打开的,即标志位于0。第3行为67.87-0.05 = 67.82,依此类推。

棘手的部分在第6行,即标志更改为1,即正在抽水。我们可以看到Tank 1的1系列在第11行结束。water_level的记录峰值为67.96。因此,从第6行到第10行的增长率现在可以在下面的公式中看到。

(67.96-第5行的值,遵循减少模式)/计数器的步数,在这种情况下为6

此计算将继续进行到Tank 2。

感谢您期待解决方案。

更新。

@manotheshark。这是一个好的开始。但这并不能很好地概括。当我将第12到16行包括在内时,它将产生错误的输出。也就是说,它不会从第11行下降0.05。

df <- data.frame(
  Water_level = c(67.92, rep(NA,9),67.96, rep(NA,5),10.5,rep(NA,8),20),
  Flag = c(rep(0,5),rep(1,6),rep(0,5),rep(0,5),rep(1,5)),
  Tank= c(rep(1, 16), rep(2, 10)),
  Counter = c(seq(1:5),seq(1:6),seq(1:5), seq(1:5),seq(1:5))
)
df

   Water_level Flag Tank Counter
1        67.92    0    1       1
2           NA    0    1       2
3           NA    0    1       3
4           NA    0    1       4
5           NA    0    1       5
6           NA    1    1       1
7           NA    1    1       2
8           NA    1    1       3
9           NA    1    1       4
10          NA    1    1       5
11       67.96    1    1       6
12          NA    0    1       1
13          NA    0    1       2
14          NA    0    1       3
15          NA    0    1       4
16          NA    0    1       5
17       10.50    0    2       1
18          NA    0    2       2
19          NA    0    2       3
20          NA    0    2       4
21          NA    0    2       5
22          NA    1    2       1
23          NA    1    2       2
24          NA    1    2       3
25          NA    1    2       4
26       20.00    1    2       5

运行解决方案的输出如下所示。第12行应为67.96-0.05 = 67.91。

   Water_level Flag Tank Counter
1     67.92000    0    1       1
2     67.87000    0    1       2
3     67.82000    0    1       3
4     67.77000    0    1       4
5     67.72000    0    1       5
6     67.30167    1    1       1
7     67.43333    1    1       2
8     67.56500    1    1       3
9     67.69667    1    1       4
10    67.82833    1    1       5
11    67.96000    1    1       6
12    67.37000    0    1       1
13    67.32000    0    1       2
14    67.27000    0    1       3
15    67.22000    0    1       4
16    67.17000    0    1       5
17    10.50000    0    2       1
18    10.45000    0    2       2
19    10.40000    0    2       3
20    10.35000    0    2       4
21    10.30000    0    2       5
22    12.24000    1    2       1
23    14.18000    1    2       2
24    16.12000    1    2       3
25    18.06000    1    2       4
26    20.00000    1    2       5

1 个答案:

答案 0 :(得分:0)

未经测试是否可以在多个油箱循环中使用。将data.frame转换为data.table

library(data.table)
setDT(df)

# calculate tank levels when dropping with Flag of 0
df[Flag == 0, Water_level := first(Water_level) - 0.05 * (.I - first(.I)), by = .(Flag, Tank)]

# use sequence to determine tank levels when filling from previous minimum to new max
df[Flag == 1, Water_level := seq(df[Flag == 0, last(Water_level), by = .(Flag, Tank)][,V1][.GRP], last(Water_level), length.out = .N + 1)[-1], by = .(Flag, Tank)]

> df
    Water_level Flag Tank Counter
 1:       67.92    0    1       1
 2:       67.87    0    1       2
 3:       67.82    0    1       3
 4:       67.77    0    1       4
 5:       67.72    0    1       5
 6:       67.76    1    1       1
 7:       67.80    1    1       2
 8:       67.84    1    1       3
 9:       67.88    1    1       4
10:       67.92    1    1       5
11:       67.96    1    1       6
12:       10.50    0    2       1
13:       10.45    0    2       2
14:       10.40    0    2       3
15:       10.35    0    2       4
16:       10.30    0    2       5
17:       12.24    1    2       1
18:       14.18    1    2       2
19:       16.12    1    2       3
20:       18.06    1    2       4
21:       20.00    1    2       5
    Water_level Flag Tank Counter