Создать новый столбец с условием по повторяющимся значениям и при наличии точек останова - PullRequest
1 голос
/ 31 марта 2020

Мои данные о 40 животных (идентификаторах) с местоположениями по телеметрии, и я уже предусмотрел 3 области. Первый - AR, где находится зона размножения, AM миграция, а AA - зона нагула. Первые локации всех животных в AR. Но иногда животное еще в период размножения (на AR), но может go до 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 х раз и после этого есть один или до 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") 

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

1 Ответ

0 голосов
/ 01 апреля 2020

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

  • Если число последовательных AM равно <20 </li>
  • Если следующий пункт назначения - , а не 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)
...