在数据框列中为每个值找到第一个先前的较低值

时间:2018-06-25 08:16:23

标签: r dplyr

给出以下数据框:

set.seed(1)

my_df = data.frame(x = rep(words[1:5], 50) %>% sort(),
                 y = 1:250,
                 z = sample(seq(from = 30 , to = 90, by = 0.1), size = 250, replace = T)) 




my_df %>% head(30)
   x  y    z
1  a  1 45.9
2  a  2 52.3
3  a  3 64.4
4  a  4 84.5
5  a  5 42.1
6  a  6 83.9
7  a  7 86.7
8  a  8 69.7
9  a  9 67.8
10 a 10 33.7
11 a 11 42.3
12 a 12 40.6
13 a 13 71.2
14 a 14 53.0
15 a 15 76.2
16 a 16 59.9
17 a 17 73.1
18 a 18 89.6
19 a 19 52.8
20 a 20 76.7
21 a 21 86.1
22 a 22 42.7
23 a 23 69.1
24 a 24 37.5
25 a 25 46.0
26 a 26 53.2
27 a 27 30.8
28 a 28 52.9
29 a 29 82.2
30 a 30 50.4

我想使用dplyr mutate创建以下列

对于z列中的每个值,请显示z中第一个值较低的行索引。

例如:

第8行显示5

第22行显示12

2 个答案:

答案 0 :(得分:1)

我不确定如何使用dplyr进行此操作,但这是使用自非设备联接的data.table尝试

library(data.table)

setDT(my_df) %>% #convert to data.table
  # Run a self non-equi join and find the closest lower value
  .[., .N - which.max(rev(z < i.z)) + 1L, on = .(y <= y), by = .EACHI] %>%
  # filter the cases where there are no such values
  .[y != V1] %>%
  # join the result back to the original data
  my_df[., on = .(y), res := V1]

head(my_df, 22)
#     x  y    z res
#  1: a  1 45.9  NA
#  2: a  2 52.3   1
#  3: a  3 64.4   2
#  4: a  4 84.5   3
#  5: a  5 42.1  NA
#  6: a  6 83.9   5
#  7: a  7 86.7   6
#  8: a  8 69.7   5
#  9: a  9 67.8   5
# 10: a 10 33.7  NA
# 11: a 11 42.3  10
# 12: a 12 40.6  10
# 13: a 13 71.2  12
# 14: a 14 53.0  12
# 15: a 15 76.2  14
# 16: a 16 59.9  14
# 17: a 17 73.1  16
# 18: a 18 89.6  17
# 19: a 19 52.8  12
# 20: a 20 76.7  19
# 21: a 21 86.1  20
# 22: a 22 42.7  12

答案 1 :(得分:0)

我设法找到了受启发的dplyr解决方案 通过使用rollapply给我其他问题之一的解决方案 在此link中。

set.seed(1)

my_df = data.frame(x = rep(words[1:5], 50) %>% sort(),
                   y = 1:250,
                   z = sample(seq(from = 30 , to = 90, by = 0.1), size = 250, replace = T)) 


my_df %>%
  mutate(First_Lower_z_Backwards = row_number() - rollapply(z, 
                                                            width = list((0:(-n()))), 
                                                            FUN = function(x) which(x < x[1])[1] - 1,
                                                            fill = NA,
                                                            partial = T)) %>%
  head(22)


   x  y    z First_Lower_z_Backwards
1  a  1 45.9                      NA
2  a  2 52.3                       1
3  a  3 64.4                       2
4  a  4 84.5                       3
5  a  5 42.1                      NA
6  a  6 83.9                       5
7  a  7 86.7                       6
8  a  8 69.7                       5
9  a  9 67.8                       5
10 a 10 33.7                      NA
11 a 11 42.3                      10
12 a 12 40.6                      10
13 a 13 71.2                      12
14 a 14 53.0                      12
15 a 15 76.2                      14
16 a 16 59.9                      14
17 a 17 73.1                      16
18 a 18 89.6                      17
19 a 19 52.8                      12
20 a 20 76.7                      19
21 a 21 86.1                      20
22 a 22 42.7                      12