Python pandas dataframe в словарь


111

У меня есть фрейм данных с двумя столбцами, и я собираюсь преобразовать его в словарь Python - первый столбец будет ключом, а второй - значением. Заранее спасибо.

Фрейм данных:

    id    value
0    0     10.2
1    1      5.7
2    2      7.4

возможный дубликат: stackoverflow.com/questions/18012505/…
dalloliogm


4
@perigee: Можете ли вы принять один из ответов (если он полезен), чтобы отметить вопрос как решенный? Это поможет и другим пользователям.
MERose

если у вас есть идентификатор, соответствующий индексу, вы должны установить его как index.
Фарис

Ответы:


152

См. Документацию для to_dict. Вы можете использовать это так:

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

И если у вас есть только один столбец, чтобы избежать имени столбца, это также уровень в 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

48

Если вам нужен простой способ сохранить дубликаты, вы можете использовать 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

OP не просил наиболее эффективного ответа, поэтому я думаю, что @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

Я нашел этот вопрос, пытаясь сделать словарь из трех столбцов фрейма данных pandas. В моем случае фрейм данных имеет столбцы 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.