Создать новый столбец с условием по повторяющимся значениям и при наличии точек останова

У меня данные около 40 животных (id) с локациями по телеметрии, и я уже оговорил 3 района. Первый - AR, где находится район размножения, AM миграция, а AA - район нагула. Первая локация всех животных находится в AR. Но иногда животное еще находится в периоде размножения (в AR), но может несколько раз выходить в AM, а потом возвращаться в AR. Только когда у животных осталось всего AM, они начали миграцию, пока не достигли места нагула AA. Итак, они начинаются в AR, затем начинают миграцию AM и затем прибывают в район нагула AA.

Я пытаюсь создать новый столбец с некоторыми условиями, которые я еще не знаю, как это сделать, например, у меня есть этот фрейм данных

id     area   
2304   AR
2304   AR
2304   AR
2304   AM  #this AM for example, can repeat until 20 times and then came back to AR
2304   AM
2304   AR
2304   AR
2304   AR
2304   AM
2304   AM
2304   AM
2304   AM
2304   ...
2304   AM
2304   AM
2304   AM
2304   AA
2304   AA
2304   ...
2304   AA

Итак, когда есть AR x раз и после этого есть один или до 20 утра и возвращаются у AR, я хочу новую колонку с AR. К тому моменту, когда у меня будет AM x раз и только AM, без возврата к AR, я хочу новую колонку с AM. Как это:

И АА это нормально, АА = АА всегда

Я ожидал этого:

id    area    fixed_area
2304   AR      AR
2304   AR      AR
2304   AR      AR
2304   AM      AR  #this AM for example, can repeat until 20 times and then came back to AR
2304   AM      AR
2304   AR      AR
2304   AR      AR
2304   AR      AR
2304   AM      AM
2304   AM      AM
2304   AM      AM
2304   AM      AM
2304   ...     ...
2304   AM      AM
2304   AM      AM
2304   AM      AM
2304   AA      AA
2304   AA      AA
2304   ...    ...
2304   AA      AA

Я пробовал это:

но AA отсутствует, возможно, проблема в том, что нужно разделить это животное (id)

> table(df$area)

   AA    AM    AR 
31460 39101 28820 

class(df$area)
[1] "character"
> idx <- with(rle(as.character(df$area)), rep(seq_along(lengths), lengths))
> df$fixed_area <- with(df, replace(area, idx < max(idx[area == 'AM']), 'AR'))
> table(df$fixed_area)

   AM    AR 
  145 99236 
> 

После этого я вставил фрейм данных, но в моем фрейме данных более 90 000 строк, поэтому я скопировал только заглавные значения.

> dput(head(df))
structure(list(DeployID = c("111868_16", "111868_16", "111868_16", 
"111868_16", "111868_16", "111868_16"), Start = structure(c(1477323868, 
1477323946, 1477324002, 1477324044, 1477324260, 1477324480), class = c("POSIXct", 
"POSIXt"), tzone = "GMT"), End = structure(c(1477323944, 1477324000, 
1477324042, 1477324170, 1477324458, 1477324542), class = c("POSIXct", 
"POSIXt"), tzone = "GMT"), What = structure(c(1L, 1L, 1L, 1L, 
1L, 1L), .Label = c("Dive", "Message", "Surface"), class = "factor"), 
    Shape = structure(c(2L, 4L, 3L, 2L, 2L, 2L), .Label = c("", 
    "Square", "U", "V"), class = "factor"), DepthMean = c(14.5, 
    16.5, 13, 14.5, 11, 12.5), DurationMean = c(76, 54, 40, 126, 
    198, 62), DepthMin = c(14.5, 16.5, 13, 14.5, 11, 12.5), DepthMax = c(14.5, 
    16.5, 13, 14.5, 11, 12.5), depth_range = structure(c(1L, 
    1L, 1L, 1L, 1L, 1L), .Label = c("shallow", "deep"), class = c("ordered", 
    "factor")), MidTime = structure(c(1477323906, 1477323973, 
    1477324022, 1477324107, 1477324359, 1477324511), class = c("POSIXct", 
    "POSIXt"), tzone = "GMT"), year = c(2016, 2016, 2016, 2016, 
    2016, 2016), id = c("111868_16", "111868_16", "111868_16", 
    "111868_16", "111868_16", "111868_16"), segmentid = c("111868_16", 
    "111868_16", "111868_16", "111868_16", "111868_16", "111868_16"
    ), mu.x = c(-4446545.25191192, -4446557.10576816, -4446565.77504969, 
    -4446580.81370994, -4446625.40007808, -4446652.29459533), 
    mu.y = c(-2305423.86124176, -2305461.88537725, -2305489.69364377, 
    -2305537.93137917, -2305680.93056743, -2305767.17264774), 
    lon = c(-39.9439956132156, -39.944102098218, -39.944179975699, 
    -39.9443150702825, -39.9447155964422, -39.9449571940013), 
    lat = c(-20.3985940756941, -20.3989161274532, -20.3991516537744, 
    -20.3995602097098, -20.4007713539709, -20.4015017842338), 
    lq_closest_filt = c(7L, 7L, 7L, 7L, 7L, 7L), dt_closest_filt = c(0.0516666666666667, 
    0.0702777777777778, 0.0838888888888889, 0.1075, 0.1775, 0.219722222222222
    ), dist_closest_filt = c(0.103680210832692, 0.141026573116106, 
    0.168339162761167, 0.215717097671267, 0.356168027785347, 
    0.440874049523752), rel.angle = c(NA_real_, NA_real_, NA_real_, 
    NA_real_, NA_real_, NA_real_), speed = c(NA_real_, NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_), depth_bin = structure(c(1L, 
    1L, 1L, 1L, 1L, 1L), .Label = c("(0,50]", "(50,100]", "(100,150]", 
    "(150,200]", "(200,250]", "(250,300]", "(300,350]", "(350,400]", 
    "(400,450]", "(450,500]", "(500,550]", "(550,600]", "(600,650]", 
    "(650,700]"), class = "factor"), bat = structure(list(depth = c(-59L, 
    -59L, -59L, -59L, -59L, -59L)), row.names = c(NA, 6L), class = "data.frame"), 
    area = c("AR", "AR", "AR", "AR", "AR", "AR")), row.names = c(NA, 
6L), class = "data.frame") 

Кто-то знает, как это исправить? Спасибо!


person Érika Soares Coelho    schedule 31.03.2020    source источник
comment
Мне не совсем понятно, что вы хотите здесь сделать: вам нужен новый столбец fixed_area с уровнями AA , AR и AM на основе уже существующей области столбца с теми же уровнями? Но разница должна заключаться в том, что он исключает короткие поездки (‹ 20 раз) из AR в AM для каждого отдельного животного?   -  person user12256545    schedule 31.03.2020
comment
Да, я хочу новый столбец на основе столбца «площадь». Некоторые животные все еще находятся в периоде размножения (AR), но они могут иногда выходить и заходить в район миграции (AM), но они еще не начали миграцию, поэтому они снова вернулись в район размножения (AR), и это перемещение может быть несколько раз. Например, AR, AR, AR, AR, AM, AM, AR, AR, AM, AM, AR, AR это животное находится в периоде размножения (AR) еще потому, что они уходят в район миграции (AM), а затем возвращаются в район размножения (AR), и это перемещение в район миграции (AM) может иметь до 20 локаций . Да, по удостоверению личности   -  person Érika Soares Coelho    schedule 31.03.2020
comment
Животное начинает миграцию (AM) только тогда, когда есть только AM, AM, AM ... AM, а когда есть AA, где место кормления, справа от него, AA это AA   -  person Érika Soares Coelho    schedule 31.03.2020
comment
@user12256545 user12256545 Я тоже отредактировал свой пост   -  person Érika Soares Coelho    schedule 31.03.2020


Ответы (1)


Похоже, вам может понадобиться несколько правил, чтобы решить, какие строки с AM станут AR.

  • Если количество последовательных AM равно ‹ 20
  • Если следующий пункт назначения не AA

Одним из подходов может быть добавление столбцов, связанных с этими двумя правилами, с помощью rle. Один столбец будет иметь lengths для количества последовательных значений в повторяющейся последовательности. Другой столбец будет иметь «следующую» область. Это было бы важно, чтобы решить, находится ли пункт назначения обратно в район размножения или далее в район нагула.

Наконец, вы можете использовать условный оператор и изменить те строки с AM на AR, которые соответствуют этим критериям:

  • Текущий area AM
  • Следующее area после не AA
  • Количество повторяющихся значений меньше 20

Вот код:

df_rle <- rle(df$area)
df2 <- cbind(df, next_area = with(df_rle, rep(c(values[-1], NA), lengths)),
                 count = with(df_rle, rep(lengths, lengths)))
df2$area <- ifelse(with(df2, area == "AM" & next_area != "AA" & count < 20),
                   "AR", df2$area)
person Ben    schedule 31.03.2020