фрейм даних python pandas до словника


111

У мене є рамка даних двох стовпців, і я маю намір перетворити його в словник python - перший стовпець буде ключовим, а другий - значенням. Спасибі заздалегідь.

Рамка даних:

    id    value
0    0     10.2
1    1      5.7
2    2      7.4

можливо дублікат: stackoverflow.com/questions/18012505 / ...
dalloliogm


4
@perigee: Чи можете ви прийняти один із відповідей (якщо це корисно), щоб позначити питання вирішеним? Це допоможе і іншим користувачам.
MERose

якщо у вас є ідентифікатор, який відповідає індексу, слід встановити його як індекс.
Фаріс

Відповіді:


152

Дивіться документи для to_dict. Ви можете використовувати його так:

df.set_index('id').to_dict()

І якщо у вас є лише один стовпець, щоб уникнути назви стовпця також є рівнем у диктаті (насправді в цьому випадку ви використовуєте Series.to_dict()):

df.set_index('id')['value'].to_dict()

14
Зауважте, що ця команда втратить дані, якщо в стовпцях ідентифікаторів будуть надлишкові значення: >>> ptest = p.DataFrame([['a',1],['a',2],['b',3]], columns=['id', 'value']) >>> ptest.set_index('id')['value'].to_dict()
dalloliogm

9
Треба сказати, що в цьому документі немає нічого, що могло б дати мені відповідь на це запитання.
Бен Фултон

@bombayquant дивіться відповіді DSM та мої відповіді нижче. Зауважте, що це 4-річна дискусія.
dalloliogm

66
mydict = dict(zip(df.id, df.value))

1
Примітка: якщо індекс є потрібним словниковим ключем, тоді виконайте: dict (zip (df.index, df.value))
aLbAc

47

Якщо ви хочете простий спосіб збереження дублікатів, ви можете скористатися groupby:

>>> ptest = pd.DataFrame([['a',1],['a',2],['b',3]], columns=['id', 'value']) 
>>> ptest
  id  value
0  a      1
1  a      2
2  b      3
>>> {k: g["value"].tolist() for k,g in ptest.groupby("id")}
{'a': [1, 2], 'b': [3]}

1
Приємне та елегантне рішення, але в таблиці на 50-ти рядах це приблизно в 6 разів повільніше мого негарного рішення нижче.
dalloliogm

@dalloliogm: ви могли б навести приклад таблиці, яка відбувається? Якщо він в шість разів повільніше, ніж цикл Python, у пандах може виникнути помилка продуктивності.
DSM

23

Відповіді joris у цій темі та punchagan у дубльованій нитці дуже елегантні, проте вони не дадуть правильних результатів, якщо стовпець, який використовується для клавіш, містить якесь дублюване значення.

Наприклад:

>>> ptest = p.DataFrame([['a',1],['a',2],['b',3]], columns=['id', 'value']) 
>>> ptest
  id  value
0  a      1
1  a      2
2  b      3

# note that in both cases the association a->1 is lost:
>>> ptest.set_index('id')['value'].to_dict()
{'a': 2, 'b': 3}
>>> dict(zip(ptest.id, ptest.value))
{'a': 2, 'b': 3}

Якщо у вас є копії записів і ви не хочете їх втрачати, ви можете використовувати цей потворний, але робочий код:

>>> mydict = {}
>>> for x in range(len(ptest)):
...     currentid = ptest.iloc[x,0]
...     currentvalue = ptest.iloc[x,1]
...     mydict.setdefault(currentid, [])
...     mydict[currentid].append(currentvalue)
>>> mydict
{'a': [1, 2], 'b': [3]}

2
Вибачте від форматування через відсутність блоку в коментарях:mydict = defaultdict(list)\n for (key, val) in ptest[["id", "value"]].itertuples(index=False):\n mydict[key].append(val)
Midnighter

1
Хоча не такий елегантний, як однолінійний, мені подобалося ваше рішення набагато більше.
Пітер Магуайр

9

Найпростіше рішення:

df.set_index('id').T.to_dict('records')

Приклад:

df= pd.DataFrame([['a',1],['a',2],['b',3]], columns=['id','value'])
df.set_index('id').T.to_dict('records')

Якщо у вас є кілька значень, таких як val1, val2, val3 тощо, і ви хочете їх як списки, тоді використовуйте наведений нижче код:

df.set_index('id').T.to_dict('list')

1
що recordsтут означає?
mingchau

1
@mingchau recordsтут маю на увазі ‘records’ : list like [{column -> value}, … , {column -> value}] Дивіться pandas.pydata.org/pandas-docs/stable/reference/api/…
AmuletxHeart

8

у деяких версіях код нижче може не працювати

mydict = dict(zip(df.id, df.value))

тому зробіть це явним

id_=df.id.values
value=df.value.values
mydict=dict(zip(id_,value))

Зауважте, що я використовував id_, оскільки слово id - це зарезервоване слово


7

Ви можете використовувати "розуміння диктату"

my_dict = {row[0]: row[1] for row in df.values}

Цикл за допомогою панд не є найбільш ефективним з точки зору використання пам'яті. Дивіться: engineering.upside.com/…
tda

ОП не просила найефективнішої відповіді, тому я думаю, що @Dongwan Kim запропонував чудове альтернативне рішення.
Економіст

3

Ще одне (трохи коротше) рішення для не втрати повторюваних записів:

>>> ptest = pd.DataFrame([['a',1],['a',2],['b',3]], columns=['id','value'])
>>> ptest
  id  value
0  a      1
1  a      2
2  b      3

>>> pdict = dict()
>>> for i in ptest['id'].unique().tolist():
...     ptest_slice = ptest[ptest['id'] == i]
...     pdict[i] = ptest_slice['value'].tolist()
...

>>> pdict
{'b': [3], 'a': [1, 2]}

1

Список потрібен як значення словника. Цей код зробить трюк.

from collections import defaultdict
mydict = defaultdict(list)
for k, v in zip(df.id.values,df.value.values):
    mydict[k].append(v)

1

Я знайшов це питання, намагаючись скласти словник із трьох стовпців фрейму даних панди. У моєму випадку кадр даних містить стовпці A, B і C (скажімо, A і B - географічні координати довготи та широти, а C - країна / штат / тощо, що в більшій чи меншій мірі).

Я хотів, щоб словник з кожною парою значень A, B (ключ словника) відповідав значенню C (значення словника) у відповідному рядку (кожна пара значень A, B гарантується унікальним завдяки попередній фільтрації, але це можливо в цьому контексті мати однакове значення C для різних пар значень A, B), тому я зробив:

mydict = dict(zip(zip(df['A'],df['B']), df['C']))

Використання pandas to_dict () також працює:

mydict = df.set_index(['A','B']).to_dict(orient='dict')['C']

(жоден із стовпців A або B не використовувався як індекс перед виконанням рядка, що створює словник)

Обидва підходи швидкі (менше однієї секунди на фреймі даних із 85-рядковими рядками, 5-річний швидкий двоядерний ноутбук).

Причини, які я публікую це:

  1. для тих, хто потребує такого рішення
  2. якщо хтось знає швидше виконання рішення (наприклад, на мільйони рядків), я буду вдячний за відповідь.

0
def get_dict_from_pd(df, key_col, row_col):
    result = dict()
    for i in set(df[key_col].values):
        is_i = df[key_col] == i
        result[i] = list(df[is_i][row_col].values)
    return result

це мій розріз, базовий цикл


0

Це моє рішення:

import pandas as pd
df = pd.read_excel('dic.xlsx')
df_T = df.set_index('id').T
dic = df_T.to_dict('records')
print(dic)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.