преобразовать пандас датафрейм в словарь с несколькими ключами - PullRequest
0 голосов
/ 05 сентября 2018

Я пытаюсь преобразовать фрейм данных в словарь с четырьмя ключами, которые все из столбцов. У меня также есть несколько столбцов, которые я хочу вернуть значения, используя ключи, построенные из этих четырех столбцов. Я работал над циклом, но в итоге обнаружил ошибку памяти. Мне любопытно, есть ли более эффективный способ для этого?

Фрейм данных выглядит следующим образом:

    Service Bill Weight Zone    Resi    UPS FedEx   USPS    DHL
    1DEA           1       2    N      33.02    9999    9999    9999
    1DEA           2       2    N      33.02    9999    9999    9999
    1DEA           3       2    N      33.02    9999    9999    9999

Я хочу иметь ключ для каждого из перевозчиков, как это:

    price[('1DEA', '1', '2', 'N', 'UPS')]=33.02
    price[('1DEA', '1', '2', 'N', 'FedEx')]=9999

Я пробовал это:

    price = {}
    carriers = ['UPS', 'FedEx', 'USPS','DHL'] 
    for carrier in carriers:
        for row in rate_keys.to_dict('records'):
              key = (row['Service'], row['Bill Weight'], row['Zone'], 
              row['Resi'], carrier)
              rate_keys[key] = row[carrier]

Ответы [ 5 ]

0 голосов
/ 05 сентября 2018

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

df.set_index(['Service', 'Bill Weight', 'Zone', 'Resi']).stack().to_dict()

{('1DEA', 1, 2, 'N', 'DHL'): 9999.0,
 ('1DEA', 1, 2, 'N', 'FedEx'): 9999.0,
 ('1DEA', 1, 2, 'N', 'UPS'): 33.02,
 ('1DEA', 1, 2, 'N', 'USPS'): 9999.0,
 ('1DEA', 2, 2, 'N', 'DHL'): 9999.0,
 ('1DEA', 2, 2, 'N', 'FedEx'): 9999.0,
 ('1DEA', 2, 2, 'N', 'UPS'): 33.02,
 ('1DEA', 2, 2, 'N', 'USPS'): 9999.0,
 ('1DEA', 3, 2, 'N', 'DHL'): 9999.0,
 ('1DEA', 3, 2, 'N', 'FedEx'): 9999.0,
 ('1DEA', 3, 2, 'N', 'UPS'): 33.02,
 ('1DEA', 3, 2, 'N', 'USPS'): 9999.0}

Постижение

{(*r[:4], c): v for r in df.values for c, v in zip(df.columns[4:], r[4:])}

{('1DEA', 1, 2, 'N', 'DHL'): 9999,
 ('1DEA', 1, 2, 'N', 'FedEx'): 9999,
 ('1DEA', 1, 2, 'N', 'UPS'): 33.02,
 ('1DEA', 1, 2, 'N', 'USPS'): 9999,
 ('1DEA', 2, 2, 'N', 'DHL'): 9999,
 ('1DEA', 2, 2, 'N', 'FedEx'): 9999,
 ('1DEA', 2, 2, 'N', 'UPS'): 33.02,
 ('1DEA', 2, 2, 'N', 'USPS'): 9999,
 ('1DEA', 3, 2, 'N', 'DHL'): 9999,
 ('1DEA', 3, 2, 'N', 'FedEx'): 9999,
 ('1DEA', 3, 2, 'N', 'UPS'): 33.02,
 ('1DEA', 3, 2, 'N', 'USPS'): 9999}
0 голосов
/ 05 сентября 2018

Во-первых,

temp = df.set_index(['Service', 'Bill', 'Weight', 'Zone']).to_dict()

Затем мы понимаем словарь, чтобы получить желаемый результат,

dict(((k+(i,)), a[i][k]) for i in temp for (k) in temp[i] )
0 голосов
/ 05 сентября 2018

если вы делаете

df = df.set_index(['Service', 'Bill','Weight','Zone'])

у вас одно и то же

выход

print(df.loc[('1DEA', 1, 2, 'N')]['UPS'])

9999.0
0 голосов
/ 05 сентября 2018

Вы, вероятно, не должны обновлять rate_keys во время зацикливания на нем. Я думаю, что последняя строка вашего примера сценария должна выглядеть так:

price[key] = row[carrier]
0 голосов
/ 05 сентября 2018

IIUC, с таким пониманием списка, как:

carriers = ['UPS', 'FedEx', 'USPS','DHL']
price = {(row['Service'], row['Bill Weight'], row['Zone'], row['Resi'], c):row[c]
     for c in carriers for _, row in df.iterrows()}

[выход]

{('1DEA', 1, 2, 'N', 'UPS'): 33.02,
 ('1DEA', 2, 2, 'N', 'UPS'): 33.02,
 ('1DEA', 3, 2, 'N', 'UPS'): 33.02,
 ('1DEA', 1, 2, 'N', 'FedEx'): 9999,
 ('1DEA', 2, 2, 'N', 'FedEx'): 9999,
 ('1DEA', 3, 2, 'N', 'FedEx'): 9999,
 ('1DEA', 1, 2, 'N', 'USPS'): 9999,
 ('1DEA', 2, 2, 'N', 'USPS'): 9999,
 ('1DEA', 3, 2, 'N', 'USPS'): 9999,
 ('1DEA', 1, 2, 'N', 'DHL'): 9999,
 ('1DEA', 2, 2, 'N', 'DHL'): 9999,
 ('1DEA', 3, 2, 'N', 'DHL'): 9999}
...