เพิ่มคอลัมน์ในดาต้าเฟรมจากรายการ


98

ฉันมี dataframe ที่มีบางคอลัมน์ดังนี้:

A   B   C  
0   
4
5
6
7
7
6
5

ช่วงเป็นไปได้ของค่าในมีเพียง 0-7

นอกจากนี้ฉันมีรายการองค์ประกอบ 8 รายการดังนี้:

List=[2,5,6,8,12,16,26,32]  //There are only 8 elements in this list

ถ้าองค์ประกอบในคอลัมน์ A เป็นnฉันต้องแทรกองค์ประกอบที่nจากรายการในคอลัมน์ใหม่โดยพูดว่า 'D'

ฉันจะทำสิ่งนี้ในคราวเดียวโดยไม่วนซ้ำทั้งดาต้าเฟรมได้อย่างไร

ดาต้าเฟรมที่ได้จะมีลักษณะดังนี้:

A   B   C   D
0           2
4           12
5           16
6           26
7           32
7           32
6           26
5           16

หมายเหตุ: ดาต้าเฟรมมีขนาดใหญ่และการวนซ้ำเป็นตัวเลือกสุดท้าย แต่ฉันยังสามารถจัดเรียงองค์ประกอบใน 'รายการ' ในโครงสร้างข้อมูลอื่น ๆ เช่น dict ได้หากจำเป็น


1
ฉันคิดว่าคุณต้องการตัวอย่างของเล่น (เล็กกว่า) พร้อมผลลัพธ์ที่ต้องการ มันฟังดูคลุมเครือเล็กน้อย
Andy Hayden

11
ไม่เคยเรียกตัวแปรว่า "รายการ" ในภาษาใดก็ได้
lucid_dreamer

คำตอบ:


51

IIUC ถ้าคุณสร้าง (ชื่อที่น่าเสียดาย) Listเป็น an ndarrayคุณสามารถทำดัชนีได้ตามธรรมชาติ

>>> import numpy as np
>>> m = np.arange(16)*10
>>> m[df.A]
array([  0,  40,  50,  60, 150, 150, 140, 130])
>>> df["D"] = m[df.A]
>>> df
    A   B   C    D
0   0 NaN NaN    0
1   4 NaN NaN   40
2   5 NaN NaN   50
3   6 NaN NaN   60
4  15 NaN NaN  150
5  15 NaN NaN  150
6  14 NaN NaN  140
7  13 NaN NaN  130

ที่นี่ฉันสร้างขึ้นใหม่mแต่ถ้าคุณใช้m = np.asarray(List)สิ่งเดียวกันควรใช้งานได้: ค่าในdf.Aจะเลือกองค์ประกอบที่เหมาะสมของm.


โปรดทราบว่าหากคุณใช้เวอร์ชันเก่าnumpyคุณอาจต้องใช้m[df.A.values]แทน - ในอดีตnumpyเล่นได้ไม่ดีกับผู้อื่นและการปรับโครงสร้างใหม่pandasบางอย่างทำให้เกิดอาการปวดหัว ตอนนี้ทุกอย่างดีขึ้นแล้ว


สวัสดี @DSM ฉันเข้าใจในสิ่งที่คุณกำลังพูด แต่ฉันได้รับข้อผิดพลาดนี้: Traceback (most recent call last): File "./b.py", line 24, in <module> d["D"] = m[d.A] IndexError: unsupported iterator index
แผงคอ

1
@mane: urf นั่นคือnumpyบั๊กเก่า ไม่d["D"] = m[d.A.values]ทำงานสำหรับคุณ?
DSM

284

เพียงกำหนดรายการโดยตรง:

df['new_col'] = mylist

ทางเลือก
แปลงรายการเป็นชุดหรืออาร์เรย์แล้วกำหนด:

se = pd.Series(mylist)
df['new_col'] = se.values

หรือ

df['new_col'] = np.array(mylist)

3
pykernel_launcher.py:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy """Entry point for launching an IPython kernel.
Ilya Rusin

@sparrow จะใช้เอpd.Seriesฟเฟกต์ dtype หรือไม่ ฉันหมายความว่ามันจะปล่อยลอยเป็นลอยและสายเป็นสตริง? หรือองค์ประกอบภายในรายการจะเริ่มต้นเป็นสตริง?
3kstc

2
@IlyaRusin มันเป็นผลบวกลวงซึ่งสามารถละเว้นได้ในกรณีนี้ ข้อมูลเพิ่มเติม: stackoverflow.com/questions/20625582/…
sparrow

1
สามารถทำให้ง่ายขึ้นเพื่อ: df ['new_col'] = pd.Series (mylist) .values
smartse

17

โซลูชันที่ปรับปรุงให้ดียิ่งขึ้นจาก @sparrow

ให้dfเป็นชุดข้อมูลของคุณและmylistเป็นรายการที่มีค่าที่คุณต้องการเพิ่มลงใน dataframe

สมมติว่าคุณต้องการเรียกคอลัมน์ใหม่ว่าnew_column

ก่อนอื่นให้สร้างรายการเป็นซีรี่ส์:

column_values = pd.Series(mylist)

จากนั้นใช้ฟังก์ชันแทรกเพื่อเพิ่มคอลัมน์ ฟังก์ชันนี้มีข้อดีคือให้คุณเลือกว่าต้องการวางคอลัมน์ในตำแหน่งใด ในตัวอย่างต่อไปนี้เราจะวางตำแหน่งคอลัมน์ใหม่ในตำแหน่งแรกจากซ้าย (โดยการตั้งค่า loc = 0)

df.insert(loc=0, column='new_column', value=column_values)

สิ่งนี้จะใช้ไม่ได้ถ้าคุณเปลี่ยนดัชนี df เป็นอย่างอื่นแล้ว 1,2,3 ... ในกรณีนี้คุณต้องเพิ่มระหว่างบรรทัด: column_values.index = df.index
Guy

8

ก่อนอื่นให้สร้าง dataframe ที่คุณมีฉันจะไม่สนใจคอลัมน์ B และ C เนื่องจากไม่เกี่ยวข้อง

df = pd.DataFrame({'A': [0, 4, 5, 6, 7, 7, 6,5]})

และการทำแผนที่ที่คุณต้องการ:

mapping = dict(enumerate([2,5,6,8,12,16,26,32]))

df['D'] = df['A'].map(mapping)

เสร็จแล้ว!

print df

เอาท์พุต:

   A   D
0  0   2
1  4  12
2  5  16
3  6  26
4  7  32
5  7  32
6  6  26
7  5  16

1
ฉันคิดว่า OP รู้วิธีทำอยู่แล้ว จากการอ่านปัญหาของฉันสร้างขึ้นDจากองค์ประกอบของAและList("ถ้าองค์ประกอบในคอลัมน์ A เป็น n ฉันต้องแทรกองค์ประกอบที่ n จากรายการในคอลัมน์ใหม่โดยพูดว่า" D "")
DSM

SO ได้กลายเป็นสถานะ F (* & พี่เลี้ยงขอบคุณ @DSM สำหรับความคิดเห็น แต่ฉันไม่สามารถแก้ไขโพสต์ได้จนกว่าจะได้รับการตรวจสอบโดยเพื่อนและจากนั้นก็ถูกปฏิเสธเพราะมันเร็วเกินไปแล้วฉันก็ สามารถตรวจสอบการแก้ไขของตัวเองได้แล้วก็สายไปแล้วเพราะคำตอบที่แย่กว่านั้น (IMHO) คือ "ยอมรับ" ดังนั้นจึงมีเมตา - พี่เลี้ยงเด็กที่มีประโยชน์น้อยกว่ามาก !!!!
Phil Cooper

ฉันไม่สามารถพูดแทนพี่เลี้ยงเด็กได้ แต่คุณจะพบว่าแนวทางของคุณเกี่ยวกับลำดับความสำคัญของอาร์เรย์แบบยาวที่ช้าลง ในแง่อื่น ๆ แน่นอนว่าการเลือกระหว่างnp.array(List)[df.A]และdf["A"].map(dict(enumerate(List)))ส่วนใหญ่เป็นเรื่องของความชอบ
DSM

สวัสดีฟิลฉันเห็นเพียงโซลูชันของคุณและความคิดเห็นของ DSM จากนั้นไม่เคยกลับมาอีกเลยเนื่องจากโซลูชันของ DSM ทำงานได้ดีสำหรับฉัน แต่ตอนนี้ดูวิธีแก้ปัญหาของคุณแล้วก็ใช้ได้เช่นกัน ฉันเรียกใช้โซลูชันของ DSM บนชุดข้อมูลของฉันประมาณ 200k รายการและทำงานในสองสามวินาทีพร้อมกับการคำนวณอื่น ๆ ทั้งหมดที่ฉันมี ฉันใหม่มากกับ python-pandas และโดยส่วนตัวแล้วไม่ได้มองหาอะไรที่หรูหราหรือยอดเยี่ยม สิ่งที่ทำงานได้ดี แต่ขอขอบคุณสำหรับการแก้ปัญหา
แผงคอ

2

คำถามเก่า; แต่ฉันพยายามใช้รหัสที่เร็วที่สุดเสมอ!

ฉันมีรายชื่อจำนวนมากที่มี 69 ล้าน uint64 np.array ()เร็วที่สุดสำหรับฉัน

df['hashes'] = hashes
Time spent: 17.034842014312744

df['hashes'] = pd.Series(hashes).values
Time spent: 17.141014337539673

df['key'] = np.array(hashes)
Time spent: 10.724546194076538
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.