Pandas: идентифицирует многоэтапные «поставки» на маршрутах грузовых автомобилей, сопоставляя веса нагрузки с соответствующими весами нагрузки - PullRequest
0 голосов
/ 18 января 2019

Сводка: В первом информационном кадре, приведенном ниже, перечислены все участки нескольких поездок, совершенных дальнобойщиками, отсортированные в хронологическом порядке и сгруппированные по идентификатору поездки.Мне нужен способ, чтобы сократить его до отдельных грузовых перевозок, сопоставив каждую значительную нагрузку с соответствующей нагрузкой.Поскольку реальный информационный фрейм содержит миллионы записей, я вполне уверен, что мне нужно делать это без итерации. Если я хочу сохранить здравый смысл.

Сложные факторы: - Значения загрузки и разгрузки для данной доставки не являютсявсегда идеальная пара - иногда есть позиционирующие ноги, во время которых груз не перевозится (я хочу избежать их захвата)

Допущения: - Нет дублирующих поставок;поставки всегда выполняются до завершения, прежде чем начнется новый. Разгрузка никогда не распределяется по нескольким получателям в какой-либо значительной степени

Если ваше решение работает без принятия вышеупомянутых предположений, я попрошу всех повсюду:приветствую тебя навсегда.Через 40 лет я представлюсь людям: «Привет! Я Светимость. Приятно познакомиться. Пожалуйста, перейдите по ссылке на этой визитной карточке и поставьте галочку рядом с ней, поставив отметку рядом с ней».

Если не окажется, что решение очень простое, в этом случае я соглашусь с тем, что очень смущен.


Итак, с самого начала. Я работаю сданные о маршрутах грузоперевозок.Любой данный грузовик, как правило, совершает многоэтапное путешествие, которое включает в себя несколько доставок груза, при этом грузовик принимает груз в точке А, разгружает его в точке В и принимает больше, выгружает его в точке С и т. Д. У меня есть списки данныхнесколько поездок и перечисляет каждый отдельный этап каждой поездки вместе с нагрузками и разгрузками груза по весу, примерно так:

import pandas as pd

df = pd.DataFrame([['ABC12321','1 Jan','2 Jan','Point A','Point B',100,  0],
                   ['ABC12321','2 Jan','2 Jan','Point B','Point C',  0,100],
                   ['ABC12321','2 Jan','2 Jan','Point C','Point D',150,  0],
                   ['ABC12321','3 Jan','3 Jan','Point D','Point E',  0,150],
                   ['QRS32123','2 Jan','2 Jan','Point Q','Point R', 50,  0],
                   ['QRS32123','2 Jan','3 Jan','Point R','Point S',  0, 50],
                   ['QRS32123','3 Jan','3 Jan','Point S','Point T', 75,  0],
                   ['QRS32123','3 Jan','4 Jan','Point T','Point U',  0,  0],
                   ['QRS32123','4 Jan','5 Jan','Point U','Point V',  0,  2],
                   ['QRS32123','5 Jan','6 Jan','Point V','Point W',  0, 73]],
           columns=['Trip_ID','Start_Date','End_Date','Start_Location','End_Location','Onload','Offload'])

print(df)

.

    Trip_ID Start_Date End_Date Start_Location End_Location  Onload  Offload
0  ABC12321      1 Jan    2 Jan        Point A      Point B     100        0
1  ABC12321      2 Jan    2 Jan        Point B      Point C       0      100
2  ABC12321      2 Jan    2 Jan        Point C      Point D     150        0
3  ABC12321      3 Jan    3 Jan        Point D      Point E       0      150
4  QRS32123      2 Jan    2 Jan        Point Q      Point R      50        0
5  QRS32123      2 Jan    3 Jan        Point R      Point S       0       50
6  QRS32123      3 Jan    3 Jan        Point S      Point T      75        0
7  QRS32123      3 Jan    4 Jan        Point T      Point U       0        0
8  QRS32123      4 Jan    5 Jan        Point U      Point V       0        2
9  QRS32123      5 Jan    6 Jan        Point V      Point W       0       73

То, что я хочу, - это уплотнениеэто сводится к отдельным поставкам путем сочетания веса нагрузки с соответствующим весом нагрузки.В случае успеха вышеприведенный кадр данных даст следующее:

    Trip_ID Start_Date End_Date Start_Location End_Location
0  ABC12321      1 Jan    2 Jan        Point A      Point C
1  ABC12321      2 Jan    3 Jan        Point C      Point E
2  QRS32123      2 Jan    3 Jan        Point Q      Point S
3  QRS32123      3 Jan    6 Jan        Point S      Point W

Если бы у меня была только одна значительная нагрузка и разгрузка на идентификатор поездки, это было бы очень просто;Я получал бы все записи, в которых нагрузка соответствовала минимальному порогу, который считается значимым, затем то же самое для разгрузки, а затем объединял бы их, например, так:

# If starting from this:
df = pd.DataFrame([['ABC12321','1 Jan','2 Jan','Point A','Point B',100,  0],
                   ['ABC12321','2 Jan','2 Jan','Point B','Point C',  0,100],
                   ['QRS32123','3 Jan','3 Jan','Point S','Point T', 75,  0],
                   ['QRS32123','3 Jan','4 Jan','Point T','Point U',  0,  0],
                   ['QRS32123','4 Jan','5 Jan','Point U','Point V',  0,  2],
                   ['QRS32123','5 Jan','6 Jan','Point V','Point W',  0, 73]],
           columns=['Trip_ID','Start_Date','End_Date','Start_Location','End_Location','Onload','Offload'])

# ...Then do this:
df2 = df.loc[df['Onload']>5,['Trip_ID','Start_Date','Start_Location',]]
df3 = df.loc[df['Offload']>5,['Trip_ID','End_Date','End_Location',]]
df_final = df2.merge(df3, how='left', on='Trip_ID')
df_final = df_final.reindex(columns=['Trip_ID','Start_Date','End_Date','Start_Location','End_Location'])

... В результате это:

print(df)

    Trip_ID Start_Date End_Date Start_Location End_Location  Onload  Offload
0  ABC12321      1 Jan    2 Jan        Point A      Point B     100        0
1  ABC12321      2 Jan    2 Jan        Point B      Point C       0      100
2  QRS32123      3 Jan    3 Jan        Point S      Point T      75        0
3  QRS32123      3 Jan    4 Jan        Point T      Point U       0        0
4  QRS32123      4 Jan    5 Jan        Point U      Point V       0        2
5  QRS32123      5 Jan    6 Jan        Point V      Point W       0       73

print(df2)

    Trip_ID Start_Date Start_Location
0  ABC12321      1 Jan        Point A
2  QRS32123      3 Jan        Point S

print(df3)

    Trip_ID End_Date End_Location
1  ABC12321    2 Jan      Point C
5  QRS32123    6 Jan      Point W

print(df_final)

    Trip_ID Start_Date End_Date Start_Location End_Location
0  ABC12321      1 Jan    2 Jan        Point A      Point C
1  QRS32123      3 Jan    6 Jan        Point S      Point W

Но я не только имею дело с несколькими доставками за поездку, но и не знаю заранее, сколько.Также иногда есть позиционирующие ноги, где груз не перевозится, поэтому я не могу просто отключить разгрузку и предположить, что следующая запись после разгрузки является началом следующей доставки.

Даже тогда, еслиonloads и их соответствующие разгрузки отлично совпали и всегда были уникальными в данной поездке, я мог бы связать их, просто отключив оба идентификатора Trip и Onload / Offload.Но они не всегда совпадают идеально (см. Самую последнюю поездку выше), и вполне возможно, что данная поездка может включать в себя несколько нагрузок и разгрузок одинакового веса.

К счастью, я могу, по крайней мере,гарантировать, что ноги для каждой поездки отсортированы в хронологическом порядке.Таким образом, стратегия, которую я в настоящее время имею в виду для разрешения участков одной поездки:

  1. Итерация по строкам до тех пор, пока не будет найдено значение загрузки выше заданного (статического) порога, а затем запишите идентификатор поездки этой строки, Начальная дата и Начальное местоположение для новой строки в отдельном фрейме данных.
  2. Проверьте, содержит ли только что найденная строка также разгрузку выше моего порога.
    • Если нет, перебирайте оставшиеся строки до тех пор, пока не будет найдена разгрузка выше моего порога.
    • В любом случае используйте дату окончания и местоположение этой строки, чтобы заполнить новую строку из шага 1.
  3. Повторяйте до тех пор, пока не будет проверена последняя строка для этого идентификатора поездки.

Но теперь у меня есть две новые проблемы: 1) я не уверен, как выполнить итерацию таким образом, чтобы продолжить, где вы остановились (и в этот момент у меня выстрелил мозг), и 2) я бы перебирать миллионы строк. Это заняло бы целую вечность, и мне понадобится запустить его несколько раз.

Так! Есть ли лучший способ реализовать это?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...