Сводка: В первом информационном кадре, приведенном ниже, перечислены все участки нескольких поездок, совершенных дальнобойщиками, отсортированные в хронологическом порядке и сгруппированные по идентификатору поездки.Мне нужен способ, чтобы сократить его до отдельных грузовых перевозок, сопоставив каждую значительную нагрузку с соответствующей нагрузкой.Поскольку реальный информационный фрейм содержит миллионы записей, я вполне уверен, что мне нужно делать это без итерации. Если я хочу сохранить здравый смысл.
Сложные факторы: - Значения загрузки и разгрузки для данной доставки не являютсявсегда идеальная пара - иногда есть позиционирующие ноги, во время которых груз не перевозится (я хочу избежать их захвата)
Допущения: - Нет дублирующих поставок;поставки всегда выполняются до завершения, прежде чем начнется новый. Разгрузка никогда не распределяется по нескольким получателям в какой-либо значительной степени
Если ваше решение работает без принятия вышеупомянутых предположений, я попрошу всех повсюду:приветствую тебя навсегда.Через 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.
- Повторяйте до тех пор, пока не будет проверена последняя строка для этого идентификатора поездки.
Но теперь у меня есть две новые проблемы: 1) я не уверен, как выполнить итерацию таким образом, чтобы продолжить, где вы остановились (и в этот момент у меня выстрелил мозг), и 2) я бы перебирать миллионы строк. Это заняло бы целую вечность, и мне понадобится запустить его несколько раз.
Так! Есть ли лучший способ реализовать это?