python pandas dataframe ไปยังพจนานุกรม


112

ฉันมี dataframe สองคอลัมน์และตั้งใจจะแปลงเป็น python dictionary - คอลัมน์แรกจะเป็นคีย์และคอลัมน์ที่สองจะเป็นค่า ขอบคุณล่วงหน้า.

ดาต้าเฟรม:

    id    value
0    0     10.2
1    1      5.7
2    2      7.4

สามารถทำซ้ำได้: stackoverflow.com/questions/18012505/…
dalloliogm

คุณได้ตรวจสอบสิ่งนี้หรือไม่: pandas.pydata.org/pandas-docs/dev/generated/…
user2290820

4
@perigee: คุณอาจยอมรับคำตอบ (ถ้ามีประโยชน์) เพื่อทำเครื่องหมายคำถามว่าได้รับการแก้ไขแล้วหรือไม่? สิ่งนี้จะช่วยผู้ใช้รายอื่นเช่นกัน
MERose

หากคุณมี ID ที่ตรงกับดัชนีคุณควรตั้งเป็นดัชนี
Faris

คำตอบ:


156

to_dictดูเอกสารสำหรับ คุณสามารถใช้งานได้ดังนี้:

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

และถ้าคุณมีเพียงคอลัมน์เดียวเพื่อหลีกเลี่ยงชื่อคอลัมน์จะเป็นระดับใน dict (ในกรณีนี้คุณใช้Series.to_dict()):

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

14
โปรดทราบว่าคำสั่งนี้จะสูญเสียข้อมูลหากมีค่าซ้ำซ้อนในคอลัมน์ ID: >>> ptest = p.DataFrame([['a',1],['a',2],['b',3]], columns=['id', 'value']) >>> ptest.set_index('id')['value'].to_dict()
dalloliogm

9
ฉันต้องบอกว่าไม่มีอะไรในลิงก์เอกสารที่จะให้คำตอบสำหรับคำถามนี้แก่ฉัน
Ben Fulton

@bombayquant ดู DSM และคำตอบของฉันด้านล่าง โปรดทราบว่านี่เป็นการสนทนาเก่า 4 ปี
dalloliogm


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
ทางออกที่ดีและสง่างาม แต่บนตารางแถว 50k มันช้ากว่าโซลูชันที่น่าเกลียดด้านล่างประมาณ 6 เท่า
dalloliogm

@dalloliogm: คุณช่วยยกตัวอย่างตารางที่เกิดขึ้นเพื่อ? หากช้ากว่าลูป Python หกเท่าอาจมีข้อผิดพลาดด้านประสิทธิภาพในแพนด้า
DSM

24

คำตอบโดย 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]}

3
ขออภัยในการจัดรูปแบบเนื่องจากไม่มีบล็อกในความคิดเห็น:mydict = defaultdict(list)\n for (key, val) in ptest[["id", "value"]].itertuples(index=False):\n mydict[key].append(val)
Midnighter

1
แม้ว่าจะไม่สวยหรูเหมือนซับใน แต่ฉันก็ชอบโซลูชันของคุณมากกว่า
Peter Maguire

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]}

2

ฉันพบคำถามนี้ขณะพยายามสร้างพจนานุกรมจากสามคอลัมน์ของดาต้าเฟรมแพนด้า ในกรณีของฉัน dataframe มีคอลัมน์ 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 เป็นดัชนีก่อนดำเนินการบรรทัดสร้างพจนานุกรม)

ทั้งสองวิธีนั้นรวดเร็ว (น้อยกว่าหนึ่งวินาทีบนดาต้าเฟรมที่มี 85k แถวแล็ปท็อปดูอัลคอร์ความเร็ว 5 ปี)

เหตุผลที่ฉันโพสต์สิ่งนี้:

  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)

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

นี่คือ sloution ของฉันเป็นลูปพื้นฐาน


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.