Возвращает первое вхождение повторяющегося значения из условия, выполненного в столбце таблицы данных

#r #datatable

Вопрос:

У меня есть следующая функция, которая принимает data.table t и переменную target в качестве аргументов:

 checkDT <- function(t, target){
  columns <- c('A', 'B', 'C')
  for (i in columns) {
    if(suppressWarnings(is.infinite(min(t[get(i) >= target, get(i)])))){
      t <- t
    }else{
    suppressWarnings(t[get(i) > min(t[get(i) >= target, get(i)]), (i) := NA])
    }
  }
  t[]
}
 

Вот входные данные.таблица t :

 > dput(t[150:250])
structure(list(Week = structure(c(19959, 19966, 19973, 19980, 
19987, 19994, 20001, 20008, 20015, 20022, 20029, 20036, 20043, 
20050, 20057, 20064, 20071, 20078, 20085, 20092, 20099, 20106, 
20113, 20120, 20127, 20134, 20141, 20148, 20155, 20162, 20169, 
20176, 20183, 20190, 20197, 20204, 20211, 20218, 20225, 20232, 
20239, 20246, 20253, 20260, 20267, 20274, 20281, 20288, 20295, 
20302, 20309, 20316, 20323, 20330, 20337, 20344, 20351, 20358, 
20365, 20372, 20379, 20386, 20393, 20400, 20407, 20414, 20421, 
20428, 20435, 20442, 20449, 20456, 20463, 20470, 20477, 20484, 
20491, 20498, 20505, 20512, 20519, 20526, 20533, 20540, 20547, 
20554, 20561, 20568, 20575, 20582, 20589, 20596, 20603, 20610, 
20617, 20624, 20631, 20638, 20645, 20652, 20659), class = "Date"), 
    A = c(180L, 181L, 182L, 183L, 183L, 184L, 185L, 186L, 187L, 
    187L, 188L, 189L, 190L, 190L, 191L, 192L, 193L, 194L, 194L, 
    195L, 196L, 196L, 197L, 198L, 198L, 199L, 200L, 201L, 201L, 
    202L, 202L, 203L, 204L, 204L, 205L, 206L, 206L, 207L, 207L, 
    208L, 209L, 209L, 210L, 210L, 211L, 212L, 212L, 213L, 213L, 
    214L, 214L, 215L, 215L, 216L, 216L, 217L, 217L, 218L, 218L, 
    219L, 219L, 220L, 220L, 221L, 221L, 222L, 222L, 223L, 223L, 
    224L, 224L, 225L, 225L, 226L, 226L, 226L, 227L, 227L, 228L, 
    228L, 228L, 229L, 229L, 230L, 230L, 230L, 231L, 231L, 232L, 
    232L, 232L, 233L, 233L, 233L, 234L, 234L, 235L, 235L, 235L, 
    236L, 236L), B = c(163L, 164L, 165L, 166L, 166L, 167L, 168L, 
    169L, 170L, 171L, 171L, 172L, 173L, 174L, 175L, 175L, 176L, 
    177L, 178L, 178L, 179L, 180L, 181L, 181L, 182L, 183L, 183L, 
    184L, 185L, 185L, 186L, 187L, 187L, 188L, 189L, 189L, 190L, 
    191L, 191L, 192L, 193L, 193L, 194L, 194L, 195L, 196L, 196L, 
    197L, 197L, 198L, 198L, 199L, 200L, 200L, 201L, 201L, 202L, 
    202L, 203L, 203L, 204L, 204L, 205L, 205L, 206L, 206L, 207L, 
    207L, 208L, 208L, 209L, 209L, 210L, 210L, 211L, 211L, 212L, 
    212L, 213L, 213L, 213L, 214L, 214L, 215L, 215L, 216L, 216L, 
    216L, 217L, 217L, 218L, 218L, 218L, 219L, 219L, 219L, 220L, 
    220L, 221L, 221L, 221L), C = c(146L, 147L, 148L, 149L, 150L, 
    151L, 151L, 152L, 153L, 154L, 155L, 155L, 156L, 157L, 158L, 
    159L, 159L, 160L, 161L, 162L, 162L, 163L, 164L, 165L, 165L, 
    166L, 167L, 168L, 168L, 169L, 170L, 170L, 171L, 172L, 172L, 
    173L, 174L, 174L, 175L, 176L, 176L, 177L, 178L, 178L, 179L, 
    179L, 180L, 181L, 181L, 182L, 182L, 183L, 184L, 184L, 185L, 
    185L, 186L, 186L, 187L, 187L, 188L, 189L, 189L, 190L, 190L, 
    191L, 191L, 192L, 192L, 193L, 193L, 194L, 194L, 195L, 195L, 
    196L, 196L, 196L, 197L, 197L, 198L, 198L, 199L, 199L, 200L, 
    200L, 201L, 201L, 201L, 202L, 202L, 203L, 203L, 204L, 204L, 
    204L, 205L, 205L, 206L, 206L, 206L)), row.names = c(NA, -101L
), class = c("data.table", "data.frame"))
> t[175:200]
          Week   A   B   C
 1: 2025-02-15 199 183 166
 2: 2025-02-22 200 183 167
 3: 2025-03-01 201 184 168
 4: 2025-03-08 201 185 168
 5: 2025-03-15 202 185 169
 6: 2025-03-22 202 186 170
 7: 2025-03-29 203 187 170
 8: 2025-04-05 204 187 171
 9: 2025-04-12 204 188 172
10: 2025-04-19 205 189 172
11: 2025-04-26 206 189 173
12: 2025-05-03 206 190 174
13: 2025-05-10 207 191 174
14: 2025-05-17 207 191 175
15: 2025-05-24 208 192 176
16: 2025-05-31 209 193 176
17: 2025-06-07 209 193 177
18: 2025-06-14 210 194 178
19: 2025-06-21 210 194 178
20: 2025-06-28 211 195 179
21: 2025-07-05 212 196 179
22: 2025-07-12 212 196 180
23: 2025-07-19 213 197 181
24: 2025-07-26 213 197 181
25: 2025-08-02 214 198 182
26: 2025-08-09 214 198 182
 

Функция будет принимать t и возвращать одни и те же данные.таблица с любыми значениями, превышающими или равными наименьшему наибольшему значению, большему, чем, что target приведет к такому выходу, когда target имеет значение 194:

 > target
[1] 194
> t[150:225]
          Week   A   B   C
 1: 2024-08-24 180 163 146
 2: 2024-08-31 181 164 147
 3: 2024-09-07 182 165 148
 4: 2024-09-14 183 166 149
 5: 2024-09-21 183 166 150
 6: 2024-09-28 184 167 151
 7: 2024-10-05 185 168 151
 8: 2024-10-12 186 169 152
 9: 2024-10-19 187 170 153
10: 2024-10-26 187 171 154
11: 2024-11-02 188 171 155
12: 2024-11-09 189 172 155
13: 2024-11-16 190 173 156
14: 2024-11-23 190 174 157
15: 2024-11-30 191 175 158
16: 2024-12-07 192 175 159
17: 2024-12-14 193 176 159
18: 2024-12-21 194 177 160
19: 2024-12-28 194 178 161
20: 2025-01-04  NA 178 162
21: 2025-01-11  NA 179 162
22: 2025-01-18  NA 180 163
23: 2025-01-25  NA 181 164
24: 2025-02-01  NA 181 165
25: 2025-02-08  NA 182 165
26: 2025-02-15  NA 183 166
27: 2025-02-22  NA 183 167
28: 2025-03-01  NA 184 168
29: 2025-03-08  NA 185 168
30: 2025-03-15  NA 185 169
31: 2025-03-22  NA 186 170
32: 2025-03-29  NA 187 170
33: 2025-04-05  NA 187 171
34: 2025-04-12  NA 188 172
35: 2025-04-19  NA 189 172
36: 2025-04-26  NA 189 173
37: 2025-05-03  NA 190 174
38: 2025-05-10  NA 191 174
39: 2025-05-17  NA 191 175
40: 2025-05-24  NA 192 176
41: 2025-05-31  NA 193 176
42: 2025-06-07  NA 193 177
43: 2025-06-14  NA 194 178
44: 2025-06-21  NA 194 178
45: 2025-06-28  NA  NA 179
46: 2025-07-05  NA  NA 179
47: 2025-07-12  NA  NA 180
48: 2025-07-19  NA  NA 181
49: 2025-07-26  NA  NA 181
50: 2025-08-02  NA  NA 182
51: 2025-08-09  NA  NA 182
52: 2025-08-16  NA  NA 183
53: 2025-08-23  NA  NA 184
54: 2025-08-30  NA  NA 184
55: 2025-09-06  NA  NA 185
56: 2025-09-13  NA  NA 185
57: 2025-09-20  NA  NA 186
58: 2025-09-27  NA  NA 186
59: 2025-10-04  NA  NA 187
60: 2025-10-11  NA  NA 187
61: 2025-10-18  NA  NA 188
62: 2025-10-25  NA  NA 189
63: 2025-11-01  NA  NA 189
64: 2025-11-08  NA  NA 190
65: 2025-11-15  NA  NA 190
66: 2025-11-22  NA  NA 191
67: 2025-11-29  NA  NA 191
68: 2025-12-06  NA  NA 192
69: 2025-12-13  NA  NA 192
70: 2025-12-20  NA  NA 193
71: 2025-12-27  NA  NA 193
72: 2026-01-03  NA  NA 194
73: 2026-01-10  NA  NA 194
74: 2026-01-17  NA  NA  NA
75: 2026-01-24  NA  NA  NA
76: 2026-01-31  NA  NA  NA
 

Как я могу изменить эту функцию, чтобы возвращать только первую дату после выполнения условия? Таким образом, чтобы результат выглядел так:

 > t[150:225]
          Week   A   B   C
 1: 2024-08-24 180 163 146
 2: 2024-08-31 181 164 147
 3: 2024-09-07 182 165 148
 4: 2024-09-14 183 166 149
 5: 2024-09-21 183 166 150
 6: 2024-09-28 184 167 151
 7: 2024-10-05 185 168 151
 8: 2024-10-12 186 169 152
 9: 2024-10-19 187 170 153
10: 2024-10-26 187 171 154
11: 2024-11-02 188 171 155
12: 2024-11-09 189 172 155
13: 2024-11-16 190 173 156
14: 2024-11-23 190 174 157
15: 2024-11-30 191 175 158
16: 2024-12-07 192 175 159
17: 2024-12-14 193 176 159
18: 2024-12-21 194 177 160
19: 2024-12-28  NA 178 161
20: 2025-01-04  NA 178 162
21: 2025-01-11  NA 179 162
22: 2025-01-18  NA 180 163
23: 2025-01-25  NA 181 164
24: 2025-02-01  NA 181 165
25: 2025-02-08  NA 182 165
26: 2025-02-15  NA 183 166
27: 2025-02-22  NA 183 167
28: 2025-03-01  NA 184 168
29: 2025-03-08  NA 185 168
30: 2025-03-15  NA 185 169
31: 2025-03-22  NA 186 170
32: 2025-03-29  NA 187 170
33: 2025-04-05  NA 187 171
34: 2025-04-12  NA 188 172
35: 2025-04-19  NA 189 172
36: 2025-04-26  NA 189 173
37: 2025-05-03  NA 190 174
38: 2025-05-10  NA 191 174
39: 2025-05-17  NA 191 175
40: 2025-05-24  NA 192 176
41: 2025-05-31  NA 193 176
42: 2025-06-07  NA 193 177
43: 2025-06-14  NA 194 178
44: 2025-06-21  NA  NA 178
45: 2025-06-28  NA  NA 179
46: 2025-07-05  NA  NA 179
47: 2025-07-12  NA  NA 180
48: 2025-07-19  NA  NA 181
49: 2025-07-26  NA  NA 181
50: 2025-08-02  NA  NA 182
51: 2025-08-09  NA  NA 182
52: 2025-08-16  NA  NA 183
53: 2025-08-23  NA  NA 184
54: 2025-08-30  NA  NA 184
55: 2025-09-06  NA  NA 185
56: 2025-09-13  NA  NA 185
57: 2025-09-20  NA  NA 186
58: 2025-09-27  NA  NA 186
59: 2025-10-04  NA  NA 187
60: 2025-10-11  NA  NA 187
61: 2025-10-18  NA  NA 188
62: 2025-10-25  NA  NA 189
63: 2025-11-01  NA  NA 189
64: 2025-11-08  NA  NA 190
65: 2025-11-15  NA  NA 190
66: 2025-11-22  NA  NA 191
67: 2025-11-29  NA  NA 191
68: 2025-12-06  NA  NA 192
69: 2025-12-13  NA  NA 192
70: 2025-12-20  NA  NA 193
71: 2025-12-27  NA  NA 193
72: 2026-01-03  NA  NA 194
73: 2026-01-10  NA  NA  NA
74: 2026-01-17  NA  NA  NA
75: 2026-01-24  NA  NA  NA
76: 2026-01-31  NA  NA  NA
 

Ответ №1:

Возможно, что-то вроде этого:

 target = 194
target.cols = c("A", "B", "C")
t[, lapply(.SD, 
      function(x) {x[(which.max(x>=target) 1L):length(x)] <- NA;x}), 
    .SDcols = target.cols]
 

Или, чтобы перезаписать столбцы по ссылке, сохранив столбец недели нетронутым, мы можем сделать

 t[,  (target.cols) := lapply(.SD, 
       function(x) {x[(which.max(x>=target) 1L):length(x)] <- NA; x}), 
  .SDcols = target.cols]
 

Комментарии:

1. Это работает, но на выходе получается таблица data.table без Week необходимого столбца. Как я могу сделать то же самое, не потеряв эту колонку?

2. вам нужно сохранить исходную таблицу data.table или вы хотите просто перезаписать столбцы A:C новыми данными?

3. последнее. Второе заявление, которое вы предоставили, сделало именно то, что я искал. Спасибо!

Ответ №2:

Вариант tidyverse.

 library(dplyr)

mutate(t, across(A:C, ~ if_else(. >= 194 amp; 
                                lag(.) == 194 |
                                . > 194, NA_integer_, .)))

#          Week   A   B   C
# 1: 2024-08-24 180 163 146
# 2: 2024-08-31 181 164 147
# 3: 2024-09-07 182 165 148
# 4: 2024-09-14 183 166 149
# 5: 2024-09-21 183 166 150
# 6: 2024-09-28 184 167 151
# 7: 2024-10-05 185 168 151
# 8: 2024-10-12 186 169 152
# 9: 2024-10-19 187 170 153
# 10: 2024-10-26 187 171 154
# 11: 2024-11-02 188 171 155
# 12: 2024-11-09 189 172 155
# 13: 2024-11-16 190 173 156
# 14: 2024-11-23 190 174 157
# 15: 2024-11-30 191 175 158
# 16: 2024-12-07 192 175 159
# 17: 2024-12-14 193 176 159
# 18: 2024-12-21 194 177 160
# 19: 2024-12-28  NA 178 161
# 20: 2025-01-04  NA 178 162
# 21: 2025-01-11  NA 179 162
# 22: 2025-01-18  NA 180 163
# 23: 2025-01-25  NA 181 164
# 24: 2025-02-01  NA 181 165
# 25: 2025-02-08  NA 182 165
# 26: 2025-02-15  NA 183 166
# 27: 2025-02-22  NA 183 167
# 28: 2025-03-01  NA 184 168
# 29: 2025-03-08  NA 185 168
# 30: 2025-03-15  NA 185 169
# 31: 2025-03-22  NA 186 170
# 32: 2025-03-29  NA 187 170
# 33: 2025-04-05  NA 187 171
# 34: 2025-04-12  NA 188 172
# 35: 2025-04-19  NA 189 172
# 36: 2025-04-26  NA 189 173
# 37: 2025-05-03  NA 190 174
# 38: 2025-05-10  NA 191 174
# 39: 2025-05-17  NA 191 175
# 40: 2025-05-24  NA 192 176
# 41: 2025-05-31  NA 193 176
# 42: 2025-06-07  NA 193 177
# 43: 2025-06-14  NA 194 178
# 44: 2025-06-21  NA  NA 178
# 45: 2025-06-28  NA  NA 179
# 46: 2025-07-05  NA  NA 179
# 47: 2025-07-12  NA  NA 180
# 48: 2025-07-19  NA  NA 181
# 49: 2025-07-26  NA  NA 181
# 50: 2025-08-02  NA  NA 182
# 51: 2025-08-09  NA  NA 182
# 52: 2025-08-16  NA  NA 183
# 53: 2025-08-23  NA  NA 184
# 54: 2025-08-30  NA  NA 184
# 55: 2025-09-06  NA  NA 185
# 56: 2025-09-13  NA  NA 185
# 57: 2025-09-20  NA  NA 186
# 58: 2025-09-27  NA  NA 186
# 59: 2025-10-04  NA  NA 187
# 60: 2025-10-11  NA  NA 187
# 61: 2025-10-18  NA  NA 188
# 62: 2025-10-25  NA  NA 189
# 63: 2025-11-01  NA  NA 189
# 64: 2025-11-08  NA  NA 190
# 65: 2025-11-15  NA  NA 190
# 66: 2025-11-22  NA  NA 191
# 67: 2025-11-29  NA  NA 191
# 68: 2025-12-06  NA  NA 192
# 69: 2025-12-13  NA  NA 192
# 70: 2025-12-20  NA  NA 193
# 71: 2025-12-27  NA  NA 193
# 72: 2026-01-03  NA  NA 194
# 73: 2026-01-10  NA  NA  NA
 

Комментарии:

1. Зачем вам использовать tidyverse в таблице data.table? Похоже, это плохая идея — перепутать пакеты.

2. @dww: Это справедливое замечание. Поскольку и вход , и выход-это а data.table , я не думаю, что это слишком преступно. Я бы не ожидал, что это будет принято как решение, но это может послужить пищей для размышлений.