จะเพิ่มหลายคอลัมน์ในฐานข้อมูลแพนด้าในงานเดียวได้อย่างไร


123

ฉันยังใหม่กับแพนด้าและพยายามหาวิธีเพิ่มหลายคอลัมน์ให้แพนด้าพร้อมกัน ขอความช่วยเหลือใด ๆ ที่นี่ ตามหลักการแล้วฉันต้องการทำสิ่งนี้ในขั้นตอนเดียวแทนที่จะทำซ้ำหลายขั้นตอน ...

import pandas as pd

df = {'col_1': [0, 1, 2, 3],
        'col_2': [4, 5, 6, 7]}
df = pd.DataFrame(df)

df[[ 'column_new_1', 'column_new_2','column_new_3']] = [np.nan, 'dogs',3]  #thought this would work here...

คุณต้องระบุข้อผิดพลาดที่คุณพบ เมื่อฉันลองสิ่งนี้กับแพนด้า 1.0 ฉันได้รับKeyError: "None of [Index(['column_new_1', 'column_new_2', 'column_new_3'], dtype='object')] are in the [columns]"
smci

คำตอบ:


191

ฉันคาดว่าไวยากรณ์ของคุณจะใช้งานได้เช่นกัน ปัญหาเกิดขึ้นเนื่องจากเมื่อคุณสร้างคอลัมน์ใหม่ด้วยไวยากรณ์รายการคอลัมน์ (df[[new1, new2]] = ... ) แพนด้าต้องการให้ด้านขวามือเป็น DataFrame (โปรดทราบว่าจริงๆแล้วไม่สำคัญว่าคอลัมน์ของ DataFrame จะมีชื่อเดียวกันกับคอลัมน์หรือไม่ คุณกำลังสร้าง)

ไวยากรณ์ของคุณทำงานได้ดีในการกำหนดค่าสเกลาร์ให้กับคอลัมน์ที่มีอยู่และแพนด้ายังยินดีที่จะกำหนดค่าสเกลาร์ให้กับคอลัมน์ใหม่โดยใช้ไวยากรณ์คอลัมน์เดียว (df[new1] = ... ) ดังนั้นวิธีแก้ปัญหาคือการแปลงสิ่งนี้เป็นการกำหนดคอลัมน์เดียวหลาย ๆ คอลัมน์หรือสร้าง DataFrame ที่เหมาะสมสำหรับด้านขวามือ

มีหลายวิธีที่จะใช้ได้ผล:

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'col_1': [0, 1, 2, 3],
    'col_2': [4, 5, 6, 7]
})

จากนั้นทำอย่างใดอย่างหนึ่งต่อไปนี้:

1) การมอบหมายงานสามอย่างในหนึ่งเดียวโดยใช้การเปิดรายการ:

df['column_new_1'], df['column_new_2'], df['column_new_3'] = [np.nan, 'dogs', 3]

2) DataFrameขยายแถวเดียวอย่างสะดวกเพื่อให้ตรงกับดัชนีดังนั้นคุณสามารถทำได้:

df[['column_new_1', 'column_new_2', 'column_new_3']] = pd.DataFrame([[np.nan, 'dogs', 3]], index=df.index)

3) สร้างเฟรมข้อมูลชั่วคราวด้วยคอลัมน์ใหม่จากนั้นรวมกับเฟรมข้อมูลเดิมในภายหลัง:

df = pd.concat(
    [
        df,
        pd.DataFrame(
            [[np.nan, 'dogs', 3]], 
            index=df.index, 
            columns=['column_new_1', 'column_new_2', 'column_new_3']
        )
    ], axis=1
)

4) คล้ายกับก่อนหน้านี้ แต่ใช้joinแทนconcat(อาจมีประสิทธิภาพน้อยกว่า):

df = df.join(pd.DataFrame(
    [[np.nan, 'dogs', 3]], 
    index=df.index, 
    columns=['column_new_1', 'column_new_2', 'column_new_3']
))

5) การใช้ dict เป็นวิธีที่ "เป็นธรรมชาติ" มากกว่าในการสร้าง data frame ใหม่กว่าสองรายการก่อนหน้า แต่คอลัมน์ใหม่จะเรียงตามตัวอักษร (อย่างน้อยก่อน Python 3.6 หรือ 3.7 ):

df = df.join(pd.DataFrame(
    {
        'column_new_1': np.nan,
        'column_new_2': 'dogs',
        'column_new_3': 3
    }, index=df.index
))

6) ใช้.assign()กับอาร์กิวเมนต์หลายคอลัมน์

ฉันชอบตัวแปรนี้ในคำตอบของ @ zero มาก แต่เช่นเดียวกับข้อก่อนหน้าคอลัมน์ใหม่จะเรียงลำดับตามตัวอักษรเสมออย่างน้อยก็มี Python เวอร์ชันแรก ๆ :

df = df.assign(column_new_1=np.nan, column_new_2='dogs', column_new_3=3)

7) สิ่งนี้น่าสนใจ (อ้างอิงจากhttps://stackoverflow.com/a/44951376/3830997 ) แต่ฉันไม่รู้ว่าเมื่อไหร่จะคุ้มกับปัญหา:

new_cols = ['column_new_1', 'column_new_2', 'column_new_3']
new_vals = [np.nan, 'dogs', 3]
df = df.reindex(columns=df.columns.tolist() + new_cols)   # add empty cols
df[new_cols] = new_vals  # multi-column assignment works for existing cols

8) ในที่สุดก็ยากที่จะเอาชนะงานที่ได้รับมอบหมายสามอย่าง

df['column_new_1'] = np.nan
df['column_new_2'] = 'dogs'
df['column_new_3'] = 3

หมายเหตุ: หลายตัวเลือกเหล่านี้ได้รับการกล่าวถึงในคำตอบอื่น ๆ : เพิ่มหลายคอลัมน์ที่จะ DataFrame และพวกเขาตั้งเท่ากับคอลัมน์ที่มีอยู่ , มันเป็นไปได้ที่จะเพิ่มคอลัมน์หลายครั้งกับหมีแพนด้า DataFrame? , เพิ่มคอลัมน์ว่างหลายที่หมีแพนด้า DataFrame


จะไม่เข้าใกล้ # 7 ( .reindex) แก้ไขดัชนีของดาต้าเฟรมหรือไม่? ทำไมใครบางคนถึงต้องการเปลี่ยนดัชนีโดยไม่จำเป็นเมื่อเพิ่มคอลัมน์เว้นแต่จะเป็นเป้าหมายที่ชัดเจน ...
Acumenus

1
.reindex()ใช้กับcolumnsอาร์กิวเมนต์ดังนั้นจึงเปลี่ยนเฉพาะคอลัมน์ "ดัชนี" (ชื่อ) มันไม่ได้เปลี่ยนดัชนีแถว
Matthias Fripp

สำหรับวิธีการบางอย่างคุณสามารถใช้OrderedDict: เช่นdf.join(pd.DataFrame( OrderedDict([('column_new_2', 'dogs'),('column_new_1', np.nan),('column_new_3', 3)]), index=df.index ))
แฮชมูเค

@hashmuke ซึ่งเหมาะสมกับ Python เวอร์ชันแรก ๆ อาจดึงดูดโดยเฉพาะคนที่ใช้พจนานุกรมสำหรับหลาย ๆ สิ่งใน Pandas เช่นdf = pd.DataFrame({'before': [1, 2, 3], 'after': [4, 5, 6]})เทียบกับdf = pd.DataFrame(OrderedDict([('before', [1, 2, 3]), ('after', [4, 5, 6])])
Matthias Fripp

2
ในกรณีที่คุณใช้ตัวเลือกjoinนี้ตรวจสอบให้แน่ใจว่าคุณไม่มีรายการที่ซ้ำกันในดัชนีของคุณ (หรือใช้ตัวเลือกreset_indexแรก) อาจช่วยให้คุณประหยัดเวลาไม่กี่ชั่วโมงในการดีบัก
Guido

40

คุณสามารถใช้assignกับชื่อคอลัมน์และค่าตามคำบอก

In [1069]: df.assign(**{'col_new_1': np.nan, 'col2_new_2': 'dogs', 'col3_new_3': 3})
Out[1069]:
   col_1  col_2 col2_new_2  col3_new_3  col_new_1
0      0      4       dogs           3        NaN
1      1      5       dogs           3        NaN
2      2      6       dogs           3        NaN
3      3      7       dogs           3        NaN

มีวิธีการทำเช่นเดียวกันกับการรักษาลำดับเฉพาะของคอลัมน์หรือไม่?
user48956

2
คุณสามารถรักษาการสั่งซื้อที่เฉพาะเจาะจงกับ Python เวอร์ชันก่อนหน้าได้โดยการโทรกำหนดหลาย ๆ ครั้ง: df.assign(**{'col_new_1': np.nan}).assign(**{'col2_new_2': 'dogs'}).assign(**{'col3_new_3': 3})
skasch

ถ้าชื่อคอลัมน์เพียง df.assign(col_new_1=np.nan, col2_new_2='dogs', col3_new_3=3)แต่มีสตริงที่มีชื่อตัวแปรทางกฎหมาย: สิ่งนี้รักษาความสงบเรียบร้อย
Tobias Bergkvist

10

ด้วยการใช้concat :

In [128]: df
Out[128]: 
   col_1  col_2
0      0      4
1      1      5
2      2      6
3      3      7

In [129]: pd.concat([df, pd.DataFrame(columns = [ 'column_new_1', 'column_new_2','column_new_3'])])
Out[129]: 
   col_1  col_2 column_new_1 column_new_2 column_new_3
0    0.0    4.0          NaN          NaN          NaN
1    1.0    5.0          NaN          NaN          NaN
2    2.0    6.0          NaN          NaN          NaN
3    3.0    7.0          NaN          NaN          NaN

[np.nan, 'dogs',3]ไม่ได้เป็นอย่างแน่ใจว่าสิ่งที่คุณต้องการจะทำอย่างไรกับ ตอนนี้อาจตั้งเป็นค่าเริ่มต้น?

In [142]: df1 = pd.concat([df, pd.DataFrame(columns = [ 'column_new_1', 'column_new_2','column_new_3'])])
In [143]: df1[[ 'column_new_1', 'column_new_2','column_new_3']] = [np.nan, 'dogs', 3]

In [144]: df1
Out[144]: 
   col_1  col_2  column_new_1 column_new_2  column_new_3
0    0.0    4.0           NaN         dogs             3
1    1.0    5.0           NaN         dogs             3
2    2.0    6.0           NaN         dogs             3
3    3.0    7.0           NaN         dogs             3

หากมีวิธีทำส่วนที่ 2 ของคุณในขั้นตอนเดียว - ใช่ค่าคงที่ในคอลัมน์เป็นตัวอย่าง
นกวิ่ง

3

การใช้ความเข้าใจรายการpd.DataFrameและpd.concat

pd.concat(
    [
        df,
        pd.DataFrame(
            [[np.nan, 'dogs', 3] for _ in range(df.shape[0])],
            df.index, ['column_new_1', 'column_new_2','column_new_3']
        )
    ], axis=1)

ป้อนคำอธิบายภาพที่นี่


3

หากเพิ่มคอลัมน์ที่ขาดหายไปจำนวนมาก (a, b, c, .... ) ด้วยค่าเดียวกันที่นี่ 0 ฉันทำสิ่งนี้:

    new_cols = ["a", "b", "c" ] 
    df[new_cols] = pd.DataFrame([[0] * len(new_cols)], index=df.index)

โดยขึ้นอยู่กับตัวแปรที่สองของคำตอบที่ยอมรับ


0

เพียงแค่ต้องการชี้ให้เห็นว่า option2 ในคำตอบของ @Matthias Fripp

(2) ฉันไม่จำเป็นต้องคาดหวังว่า DataFrame จะทำงานในลักษณะนี้ แต่ก็ทำได้

df [['column_new_1', 'column_new_2', 'column_new_3']] = pd.DataFrame ([[np.nan, 'dogs', 3]], index = df.index)

ได้รับการบันทึกไว้ในเอกสารของแพนด้าแล้ว http://pandas.pydata.org/pandas-docs/stable/indexing.html#basics

คุณสามารถส่งรายการคอลัมน์ไปที่ [] เพื่อเลือกคอลัมน์ตามลำดับนั้น หากไม่มีคอลัมน์ใน DataFrame จะมีการเพิ่มข้อยกเว้น สามารถตั้งค่าหลายคอลัมน์ในลักษณะนี้ได้ คุณอาจพบว่าสิ่งนี้มีประโยชน์สำหรับการใช้การแปลง ( ในสถานที่ ) กับส่วนย่อยของคอลัมน์


ฉันคิดว่านี่เป็นมาตรฐานที่ดีสำหรับการกำหนดหลายคอลัมน์ ส่วนที่ทำให้ฉันประหลาดใจคือpd.DataFrame([[np.nan, 'dogs', 3]], index=df.index)การจำลองแถวเดียวที่ได้รับเพื่อสร้างดาต้าเฟรมทั้งหมดที่มีความยาวเท่ากับดัชนี
Matthias Fripp

0

หากคุณต้องการเพิ่มคอลัมน์ใหม่ที่ว่างเปล่าการทำดัชนีใหม่จะทำงานได้

df
   col_1  col_2
0      0      4
1      1      5
2      2      6
3      3      7

df.reindex(list(df)+['column_new_1', 'column_new_2','column_new_3'], axis=1)
   col_1  col_2  column_new_1  column_new_2  column_new_3
0      0      4           NaN           NaN           NaN
1      1      5           NaN           NaN           NaN
2      2      6           NaN           NaN           NaN
3      3      7           NaN           NaN           NaN

ตัวอย่างโค้ดแบบเต็ม

import numpy as np
import pandas as pd

df = {'col_1': [0, 1, 2, 3],
        'col_2': [4, 5, 6, 7]}
df = pd.DataFrame(df)
print('df',df, sep='\n')
print()
df=df.reindex(list(df)+['column_new_1', 'column_new_2','column_new_3'], axis=1)
print('''df.reindex(list(df)+['column_new_1', 'column_new_2','column_new_3'], axis=1)''',df, sep='\n')

มิฉะนั้นให้ไปหาคำตอบที่เป็นศูนย์พร้อมมอบหมาย


0

ฉันไม่สะดวกในการใช้ "ดัชนี" และอื่น ๆ ... สามารถขึ้นมาได้ดังนี้

df.columns
Index(['A123', 'B123'], dtype='object')

df=pd.concat([df,pd.DataFrame(columns=list('CDE'))])

df.rename(columns={
    'C':'C123',
    'D':'D123',
    'E':'E123'
},inplace=True)


df.columns
Index(['A123', 'B123', 'C123', 'D123', 'E123'], dtype='object')

0

คุณสามารถสร้างอินสแตนซ์ของค่าจากพจนานุกรมได้หากคุณต้องการค่าที่แตกต่างกันสำหรับแต่ละคอลัมน์และคุณไม่คิดที่จะสร้างพจนานุกรมในบรรทัดมาก่อน

>>> import pandas as pd
>>> import numpy as np
>>> df = pd.DataFrame({
  'col_1': [0, 1, 2, 3], 
  'col_2': [4, 5, 6, 7]
})
>>> df
   col_1  col_2
0      0      4
1      1      5
2      2      6
3      3      7
>>> cols = {
  'column_new_1':np.nan,
  'column_new_2':'dogs',
  'column_new_3': 3
}
>>> df[list(cols)] = pd.DataFrame(data={k:[v]*len(df) for k,v in cols.items()})
>>> df
   col_1  col_2  column_new_1 column_new_2  column_new_3
0      0      4           NaN         dogs             3
1      1      5           NaN         dogs             3
2      2      6           NaN         dogs             3
3      3      7           NaN         dogs             3

ไม่จำเป็นต้องดีไปกว่าคำตอบที่ยอมรับ แต่เป็นอีกแนวทางหนึ่งที่ยังไม่ได้ระบุไว้

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