Присвоение значений фрейму данных pandas на основе верхнего и нижнего пределов

#python-3.x #pandas

#python-3.x #pandas

Вопрос:

Недавно я столкнулся с этой проблемой, и, к сожалению, моих знаний Python недостаточно, чтобы придумать решение.

Допустим, я менеджер по логистике маршрута Сидней — Мельбурн, и в моем распоряжении следующие виды транспорта с соответствующим временем в пути для маршрута:

 df1 = pd.DataFrame()

Index    Transportation    Time
1        Plane             1:00:00
2        Rail              3:00:00
3        Truck             5:00:00
4        Bus               7:00:00
5        Ferry             9:00:00
  

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

 df2 = pd.DataFrame()

Index    Client    PremiumTime    MaxTime
1        Alan      1:00:00        3:00:00
2        Bernard   2:00:00        5:00:00
3        Cassie    2:00:00        7:00:00
4        Donald    3:00:00        7:00:00
5        Elijah    5:00:00        9:00:00
  

В этом сценарии каждый вид транспорта может быть назначен только одному клиенту, и предположим, что len(df1) == len(df2) . Чего я пытаюсь достичь здесь, так это назначить каждому клиенту один вид транспорта, чтобы я не превышал их MaxTime , и в то же время постараться удовлетворить как можно больше клиентов PremiumTime , насколько это возможно.

Пример возможного желаемого результата:

 Index    Client    PremiumTime    MaxTime    Transportation
1        Alan      1:00:00        3:00:00    Plane
2        Bernard   2:00:00        5:00:00    Truck
3        Cassie    2:00:00        7:00:00    Bus
4        Donald    3:00:00        7:00:00    Rail
5        Elijah    5:00:00        9:00:00    Ferry
  

Обратите внимание, что мне удалось достичь PremiumTime обоих Alan и Donald , что является наилучшим сценарием в этом примере.

Любая помощь или подталкивания в правильном направлении были бы весьма признательны. Спасибо!

Ответ №1:

IIUC, используйте:

 d=df1.set_index('Time')['Transportation']
#create a mapping for time and transport
cond=df2.PremiumTime.isin(df1.Time)
#check if PremiumTime from df2 is there in time in df1
  

Затем используйте np.where() для условного отображения

 df2['Transportation']=np.where(cond,df2.PremiumTime.map(d),df2.MaxTime.map(d))
print(df2)
  

Вывод

         Client PremiumTime  MaxTime Transportation
Index                                             
1         Alan     1:00:00  3:00:00          Plane
2      Bernard     2:00:00  5:00:00          Truck
3       Cassie     2:00:00  7:00:00            Bus
4       Donald     3:00:00  7:00:00           Rail
5       Elijah     5:00:00  9:00:00          Truck #note the diff in this row output
  

Комментарии:

1. спасибо за помощь! однако df2['Transportation'] должны содержать только уникальные значения. Есть ли дополнительный фильтр для этого?

2. @AdrianY я думаю, должен быть какой-то способ. К сожалению, сейчас ничего не могу придумать. Я постараюсь вернуться к вам по этому вопросу. Между тем, если это срочно, я бы посоветовал вам взять 2 dfs и код, который пока работает, и опубликовать новый вопрос, который может быть (чтобы привлечь больше внимания — новые вопросы становятся более заметными). В противном случае, если я найду что-то для работы, я прокомментирую вас. Спасибо..