เพิ่มคอลัมน์ที่มีค่าคงที่ให้กับแพนด้าดาต้าเฟรม [ซ้ำ]


104

รับ DataFrame:

np.random.seed(0)
df = pd.DataFrame(np.random.randn(3, 3), columns=list('ABC'), index=[1, 2, 3])
df

          A         B         C
1  1.764052  0.400157  0.978738
2  2.240893  1.867558 -0.977278
3  0.950088 -0.151357 -0.103219

วิธีที่ง่ายที่สุดในการเพิ่มคอลัมน์ใหม่ที่มีค่าคงที่เช่น 0 คืออะไร?

          A         B         C  new
1  1.764052  0.400157  0.978738    0
2  2.240893  1.867558 -0.977278    0
3  0.950088 -0.151357 -0.103219    0

นี่เป็นวิธีแก้ปัญหาของฉัน แต่ฉันไม่รู้ว่าเหตุใดจึงทำให้ NaN เป็นคอลัมน์ 'ใหม่'

df['new'] = pd.Series([0 for x in range(len(df.index))])

          A         B         C  new
1  1.764052  0.400157  0.978738  0.0
2  2.240893  1.867558 -0.977278  0.0
3  0.950088 -0.151357 -0.103219  NaN

9
หากคุณใช้ดัชนีก็ไม่เป็นไร df['new'] = pd.Series([0 for x in range(len(df.index))], index=df.index).
zach

5
นอกจากนี้ความเข้าใจในรายการก็ไม่จำเป็นทั้งหมดที่นี่ เพียงแค่ทำ[0] * len(df.index)
acushner

@joris ฉันหมายความว่า df ['new'] = 0 แสดงเหตุผลที่เหมาะสมของการกำหนดศูนย์ให้กับทั้งคอลัมน์ แต่ไม่ได้อธิบายว่าเหตุใดความพยายามครั้งแรกของฉันจึงแทรก NaN นี่คือคำตอบโดย Philip Cloud ในคำตอบที่ฉันยอมรับ
yemu

7
ทำง่ายๆdf['new'] = 0
flow2k

คำตอบ:


22

สาเหตุที่ทำให้NaNเป็นคอลัมน์เนื่องจากdf.indexและIndexวัตถุด้านขวามือของคุณแตกต่างกัน @zach แสดงวิธีที่เหมาะสมในการกำหนดคอลัมน์ใหม่ของศูนย์ โดยทั่วไปpandasพยายามจัดแนวดัชนีให้มากที่สุด ข้อเสียอย่างหนึ่งคือเมื่อดัชนีไม่ได้รับการจัดแนวคุณจะได้รับNaNทุกที่ที่ไม่ได้จัดแนว ลองเล่นกับวิธีการreindexและalignเพื่อให้ได้สัญชาตญาณในการจัดแนวทำงานกับวัตถุที่มีดัชนีจัดแนวบางส่วนทั้งหมดและไม่จัดแนวทั้งหมด ตัวอย่างเช่นนี่คือวิธีการDataFrame.align()ทำงานกับดัชนีที่จัดแนวบางส่วน:

In [7]: from pandas import DataFrame

In [8]: from numpy.random import randint

In [9]: df = DataFrame({'a': randint(3, size=10)})

In [10]:

In [10]: df
Out[10]:
   a
0  0
1  2
2  0
3  1
4  0
5  0
6  0
7  0
8  0
9  0

In [11]: s = df.a[:5]

In [12]: dfa, sa = df.align(s, axis=0)

In [13]: dfa
Out[13]:
   a
0  0
1  2
2  0
3  1
4  0
5  0
6  0
7  0
8  0
9  0

In [14]: sa
Out[14]:
0     0
1     2
2     0
3     1
4     0
5   NaN
6   NaN
7   NaN
8   NaN
9   NaN
Name: a, dtype: float64

11
ฉันไม่ได้ลงคะแนน แต่รหัสของคุณไม่มีความคิดเห็นทำให้ยากที่จะติดตามพร้อมกับที่คุณพยายามบรรลุในตัวอย่าง
แก้ไข

8
นี่ตอบคำถามไม่ได้จริงๆ OP กำลังถามเกี่ยวกับวิธีการเพิ่มคอลัมน์ใหม่ที่มีค่าคงที่
cs95

ฉันไม่ยอมรับว่ามีคำถามเพียงข้อเดียวที่นี่ มี "ฉันจะกำหนดค่าคงที่ให้กับคอลัมน์ได้อย่างไร" เช่นเดียวกับ "ความพยายามของฉันในการทำเช่นนี้ไม่ได้ผลในรูปแบบ X เหตุใดจึงทำงานผิดปกติ" ฉันเชื่อว่าฉันได้พูดถึงทั้งสองประเด็นแล้วอย่างแรกโดยอ้างถึงคำตอบอื่น โปรดอ่านข้อความทั้งหมดในคำตอบของฉัน
Phillip Cloud

ฉันคิดว่าปัญหาอยู่ที่คำถามมากกว่าคำตอบของคุณ มีคำถามสองข้อที่แตกต่างกันในโพสต์นี้และด้วยเหตุนี้จึงต้องมีคำตอบที่แตกต่างกันสองคำเพื่อตอบคำถาม ฉันเชื่อว่าสิ่งนี้ควรถูกตั้งค่าสถานะว่ากว้างเกินไปและผู้โพสต์ควรถามคำถามแยกกันสองคำถาม
Kevin

90

การมอบหมายงานในสถานที่ที่ง่ายสุด ๆ : df['new'] = 0

สำหรับการปรับเปลี่ยนในสถานที่ให้ดำเนินการมอบหมายโดยตรง งานนี้ถ่ายทอดโดยแพนด้าสำหรับแต่ละแถว

df = pd.DataFrame('x', index=range(4), columns=list('ABC'))
df

   A  B  C
0  x  x  x
1  x  x  x
2  x  x  x
3  x  x  x

df['new'] = 'y'
# Same as,
# df.loc[:, 'new'] = 'y'
df

   A  B  C new
0  x  x  x   y
1  x  x  x   y
2  x  x  x   y
3  x  x  x   y

หมายเหตุสำหรับคอลัมน์วัตถุ

หากคุณต้องการเพิ่มคอลัมน์ของรายการว่างนี่คือคำแนะนำของฉัน:

  • อย่าทำเช่นนี้ objectคอลัมน์เป็นข่าวร้ายในแง่ของประสิทธิภาพ คิดใหม่ว่าข้อมูลของคุณมีโครงสร้างอย่างไร
  • พิจารณาจัดเก็บข้อมูลของคุณในโครงสร้างข้อมูลแบบกระจัดกระจาย ข้อมูลเพิ่มเติม: โครงสร้างข้อมูลกระจัดกระจาย
  • หากคุณต้องจัดเก็บคอลัมน์ของรายการอย่าคัดลอกการอ้างอิงเดียวกันหลายครั้ง

    # Wrong
    df['new'] = [[]] * len(df)
    # Right
    df['new'] = [[] for _ in range(len(df))]
    

การสร้างสำเนา: df.assign(new=0)

หากคุณต้องการสำเนาแทนให้ใช้DataFrame.assign:

df.assign(new='y')

   A  B  C new
0  x  x  x   y
1  x  x  x   y
2  x  x  x   y
3  x  x  x   y

และหากคุณต้องการกำหนดหลายคอลัมน์ที่มีค่าเดียวกันก็ทำได้ง่ายๆเพียงแค่

c = ['new1', 'new2', ...]
df.assign(**dict.fromkeys(c, 'y'))

   A  B  C new1 new2
0  x  x  x    y    y
1  x  x  x    y    y
2  x  x  x    y    y
3  x  x  x    y    y

การกำหนดหลายคอลัมน์

สุดท้ายหากคุณต้องการกำหนดหลายคอลัมน์ด้วยค่าที่ต่างกันคุณสามารถใช้assignกับพจนานุกรมได้

c = {'new1': 'w', 'new2': 'y', 'new3': 'z'}
df.assign(**c)

   A  B  C new1 new2 new3
0  x  x  x    w    y    z
1  x  x  x    w    y    z
2  x  x  x    w    y    z
3  x  x  x    w    y    z

21

ด้วยแพนด้าสมัยใหม่คุณสามารถทำได้:

df['new'] = 0

1
คุณชี้ให้เห็นได้ไหมว่าคำตอบใดที่ล้าสมัย มาแสดงความคิดเห็นกันเพื่อให้ผู้เขียนมีโอกาสปรับปรุง
cs95

1
Fyi ความแตกต่างเพียงอย่างเดียวระหว่างคำตอบนี้กับคำตอบ cs95 (AKA ฉัน) คือชื่อคอลัมน์และค่า ทุกชิ้นอยู่ที่นั่น
cs95

1
ไม่มากจนล้าสมัย แต่คำตอบนี้มีรายละเอียดน้อยกว่าข้ออื่น ๆ และอ่านง่ายกว่า
Joey

1
@Joey ไม่สามารถโต้แย้งด้วยเหตุผลดังกล่าวได้ฉันคิดว่าคำตอบนี้เหมาะสำหรับผู้ที่ต้องการคัดลอกวางสิ่งที่จะได้ผลมากกว่าต้องการทำความเข้าใจและเรียนรู้เพิ่มเติมเกี่ยวกับห้องสมุด Touche.
cs95

1
@ cs95 ใช่คำตอบของคุณช่วยให้ผู้คนเรียนรู้เพิ่มเติม นอกจากนี้ df ['new'] = 0 ที่ไฮไลต์ในชื่อยังเหมาะสำหรับการอ่าน ฉันได้โหวตมากเกินไป verbose น้อยกว่า df.apply (lambda x: 0, axis = 1)
Joey

7

นี่คืออีกหนึ่งซับโดยใช้ lambdas (สร้างคอลัมน์ด้วยค่าคงที่ = 10)

df['newCol'] = df.apply(lambda x: 10, axis=1)

ก่อน

df
    A           B           C
1   1.764052    0.400157    0.978738
2   2.240893    1.867558    -0.977278
3   0.950088    -0.151357   -0.103219

หลังจาก

df
        A           B           C           newCol
    1   1.764052    0.400157    0.978738    10
    2   2.240893    1.867558    -0.977278   10
    3   0.950088    -0.151357   -0.103219   10

5
df['newCol'] = 10ยังเป็นซับเดียว (และเร็วกว่า) ข้อได้เปรียบของการใช้สมัครที่นี่คืออะไร?
cs95

2
ไม่ได้พยายามแข่งขันกับคุณที่นี่ - เพียงแค่แสดงแนวทางอื่น
Grant Shannon

@ cs95 สิ่งนี้มีประโยชน์ ฉันต้องการสร้างคอลัมน์ใหม่โดยแต่ละค่าเป็นรายการว่างแยกต่างหาก วิธีนี้ใช้ได้ผล
Yatharth Agarwal

@YatharthAgarwal ฉันจะให้คุณ แต่มันก็สมเหตุสมผลเช่นกันเพราะแพนด้าไม่ได้ออกแบบมาให้ทำงานได้ดีกับคอลัมน์ของรายการ
cs95

1
@YatharthAgarwal หากคุณต้องการกำหนดรายการว่างสิ่งนี้ยังคงเป็นโซลูชันย่อยเนื่องจากมีการใช้งาน ลองdf['new'] = [[] for _ in range(len(df))]
cs95
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.