Вырастить сгруппированный pandas кадр данных путем итеративного сравнения предыдущего элемента другого столбца - PullRequest
0 голосов
/ 11 марта 2020

Мой вопрос относится к другому вопросу, который я задал здесь , но отличается, поскольку речь идет о двух столбцах.

У меня есть pandas фрейм данных для нескольких групп (транспортных средств) время отправления и прибытия в указанный c день. Эти времена хранятся в виде строк, так что, например, «2330» соответствует 23:30 и «30» - 0:30. Эти моменты времени упорядочены в хронологическом порядке, но иногда могут пересекать линию полуночи. Я хочу указать эти моменты на 1 в новом столбце. В частности, я думаю, что мне нужно проверять (1) для каждого времени отправления, является ли оно «более ранним», чем время прибытия предыдущей записи (это означает, что отправление должно быть в новый день) и (2) для каждого времени прибытия является ли он более ранним, чем время отправления текущей записи (это означает, что прибытие должно быть в новый день).

Пример:

df = pd.DataFrame.{'group' : ["A","A","A","B","B","B"],
                   'departure' : [2030, 2300, 200, 1930, 200, 300],
                   'arrival' : [2130, 30, 230, 100, 230, 400]})

Выход

  group  departure  arrival
0     A       2030     2130
1     A       2300       30
2     A        200      230
3     B       1930      100
4     B        200      230
5     B        300      400

Желаемый результат:

  group  departure  arrival  dep_new  arr_new
0     A       2030     2130  0        0
1     A       2300       30  0        1
2     A        200      230  1        1
3     B       1930      100  0        1
4     B        200      230  1        1
5     B        300      400  1        1

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

Надеюсь, вы можете помочь!

Ответы [ 2 ]

0 голосов
/ 11 марта 2020

С помощью @Rene, думаю, мне удалось найти решение.

def _activity_nextday(df):
    deppivot = (df.departure < df.arrival.shift(1)).astype(int) # if departure is "before" arrival on previous day, then this means that departure is on new day
    arrpivot = (df.arrival < df.departure).astype(int)  # if arrival is "before" departure, then this means that arrival is on new day

    agglist = [None] * (len(arrpivot) + len(deppivot))
    agglist[::2] = deppivot
    agglist[1::2] = arrpivot
    cumlist = list(np.array(agglist).cumsum())
    d_cum = cumlist[::2]
    a_cum = cumlist[1::2]

    return pd.DataFrame({"dep_new" : d_cum, "arr_new": a_cum})

df[["dep_new", "arr_new"]] = df.groupby("group").apply(lambda x: _activity_nextday(x)).reset_index(level="group").reset_index(drop=False)[["dep_new", "arr_new"]]

Результат:

  group  departure  arrival  dep_new  arr_new
0     A       2030     2130        0        0
1     A       2300     2330        0        0
2     A        200      230        1        1
3     B       1930      100        0        1
4     B        200      230        1        1
5     B        300      400        1        1
0 голосов
/ 11 марта 2020

Вы можете попробовать:

df = pd.DataFrame({'group' : ["A","A","A","B","B","B"],
                   'departure' : [2030, 2300, 200, 1930, 200, 300],
                   'arrival' : [2130, 30, 230, 100, 230, 400]})
dep_new = list()
arr_new = list()

for grp in df.groupby('group'):
    dep_new.append((grp[1].arrival < grp[1].departure).astype(int))
    arr_new.append((grp[1].departure > grp[1].arrival.shift(1)).astype(int))

arr_new_flat = list()
for sublist in arr_new:
    for item in sublist:
        arr_new_flat.append(item)

dep_new_flat = list()
for sublist in dep_new:
    for item in sublist:
        dep_new_flat.append(item)

df['dep_new'] = dep_new_flat
df['arr_new'] = arr_new_flat

print(df)

Результат:

  group  departure  arrival  dep_new  arr_new
0     A       2030     2130        0        0
1     A       2300       30        1        1
2     A        200      230        0        1
3     B       1930      100        1        0
4     B        200      230        0        1
5     B        300      400        0        1
...