У меня фрейм данных выглядит так:

person   year   location     salary
Harry    2002   Los Angeles  $2000
Harry    2006   Boston       $3000
Harry    2007   Los Angeles  $2500
Peter    2001   New York     $2000
Peter    2002   New York     $2300
Lily     2007   New York     $7000
Lily     2008   Boston       $2300
Lily     2011   New York     $4000
Lily     2013   Boston       $3300

Я хочу выявить закономерность на уровне человека. Я хочу знать, кто уезжает из места и возвращается позже. Например, Гарри уезжает из Лос-Анджелеса и вернулся позже. Лили переехала из Нью-Йорка и вернулась позже. Что касается Лили, то можно сказать, что она тоже переехала из Бостона и вернулась позже. Меня только интересует, у кого эта выкройка, и не волнует количество туда и обратно. Поэтому в идеале результат может выглядеть так:

   person   move_back (yes/no)
   Harry    1
   Peter    0
   Lily     1
2
RandomThinker 20 Май 2021 в 04:46

3 ответа

Лучший ответ

С помощью data.table rleid вы можете:

library(dplyr)

df %>%
  arrange(person, year) %>%
  group_by(person) %>%
  mutate(val = data.table::rleid(location)) %>%
  arrange(person, location) %>%
  group_by(location, .add = TRUE) %>%
  summarise(move_back = any(val != lag(val, default = first(val)))) %>%
  summarise(move_back = as.integer(any(move_back)))

#  person move_back
#  <chr>      <int>
#1 Harry          1
#2 Lily           1
#3 Peter          0
3
Ronak Shah 20 Май 2021 в 02:22

Немного другой метод data.table , основанный на объединениях и номере строки (.I).
Обычно я отмечаю все случаи, когда местоположение человека соответствует строке, которая не является следующей строкой, а затем агрегирую.

library(data.table)
setDT(dat)

dat[, rn   := .I]
dat[, rnp1 := .I + 1]

dat[dat, on=.(person, location, rn > rnp1), back := TRUE]
dat[, .(move_back = any(back, na.rm=TRUE)), by=person]

#   person move_back
#1:  Harry      TRUE
#2:  Peter     FALSE
#3:   Lily      TRUE

Где dat был:

dat <- read.csv(text="person,year,location,salary
Harry,2002,Los Angeles,$2000
Harry,2006,Boston,$3000
Harry,2007,Los Angeles,$2500
Peter,2001,New York,$2000
Peter,2002,New York,$2300
Lily,2007,New York,$7000
Lily,2008,Boston,$2300
Lily,2011,New York,$4000
Lily,2013,Boston,$3300", header=TRUE)
1
thelatemail 20 Май 2021 в 04:24

Вы можете использовать rle для определения ситуаций, в которых есть один или несколько экземпляров повторов. (Думаю, у вашего пункта Лили было два повтора.)

lapply( split(dat, dat$person), function(x) duplicated( rle(x$location)$values))
$Harry
[1] FALSE FALSE  TRUE

$Lily
[1] FALSE FALSE  TRUE  TRUE

$Peter
[1] FALSE

Вы можете использовать sapply с sum или any, чтобы определить количество откатов или произошли ли какие-либо откаты. Если вы хотите знать, есть ли возврат на первый сайт, логика будет другой.

2
IRTFM 20 Май 2021 в 02:05