Làm cách nào để thêm nhiều cột vào khung dữ liệu gấu trúc trong một lần gán?


122

Tôi mới làm quen với gấu trúc và đang cố gắng tìm ra cách thêm nhiều cột vào gấu trúc cùng một lúc. Bất kỳ trợ giúp nào ở đây đều được đánh giá cao. Lý tưởng nhất là tôi muốn thực hiện điều này trong một bước thay vì nhiều bước lặp lại ...

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...

Bạn cần nêu rõ lỗi bạn mắc phải. Khi tôi thử điều này trên gấu trúc 1.0, tôi nhận đượcKeyError: "None of [Index(['column_new_1', 'column_new_2', 'column_new_3'], dtype='object')] are in the [columns]"
smci

Câu trả lời:


185

Tôi đã mong đợi cú pháp của bạn cũng hoạt động. Vấn đề nảy sinh vì khi bạn tạo các cột mới với cú pháp danh sách cột ( df[[new1, new2]] = ...), gấu trúc yêu cầu phía bên tay phải là DataFrame (lưu ý rằng không thực sự quan trọng nếu các cột của DataFrame có cùng tên với các cột bạn đang tạo).

Cú pháp của bạn hoạt động tốt khi gán giá trị vô hướng cho các cột hiện có và gấu trúc cũng rất vui khi chỉ định giá trị vô hướng cho một cột mới bằng cú pháp cột đơn ( df[new1] = ...). Vì vậy, giải pháp là chuyển đổi điều này thành một số nhiệm vụ cột đơn hoặc tạo DataFrame phù hợp cho phía bên tay phải.

Dưới đây là một số cách tiếp cận sẽ hoạt động:

import pandas as pd
import numpy as np

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

Sau đó, một trong những điều sau:

1) Ba nhiệm vụ trong một, sử dụng giải nén danh sách:

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

2) DataFramemở rộng một cách thuận tiện một hàng để khớp với chỉ mục, vì vậy bạn có thể thực hiện điều này:

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

3) Tạo khung dữ liệu tạm thời với các cột mới, sau đó kết hợp với khung dữ liệu ban đầu sau:

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) Tương tự như trước, nhưng sử dụng jointhay vì concat(có thể kém hiệu quả hơn):

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

5) Sử dụng dict là một cách "tự nhiên" hơn để tạo khung dữ liệu mới so với hai cách trước, nhưng các cột mới sẽ được sắp xếp theo thứ tự bảng chữ cái (ít nhất là trước Python 3.6 hoặc 3.7 ):

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

6) Sử dụng .assign()với nhiều đối số cột.

Tôi thích biến thể này trên câu trả lời của @ zero rất nhiều, nhưng giống như phiên bản trước, các cột mới sẽ luôn được sắp xếp theo thứ tự bảng chữ cái, ít nhất là với các phiên bản đầu tiên của Python:

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

7) Điều này thật thú vị (dựa trên https://stackoverflow.com/a/44951376/3830997 ), nhưng tôi không biết khi nào nó sẽ đáng gặp phải rắc rối:

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) Cuối cùng, thật khó để đánh bại ba bài tập riêng biệt:

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

Lưu ý: nhiều tùy chọn này đã được đề cập trong các câu trả lời khác: Thêm nhiều cột vào DataFrame và đặt chúng bằng một cột hiện có , Có thể thêm nhiều cột cùng một lúc vào DataFrame của gấu trúc không? , Thêm nhiều cột trống vào DataFrame của gấu trúc


Cách tiếp cận # 7 ( .reindex) sẽ không làm thay đổi chỉ mục của khung dữ liệu? Tại sao ai đó lại muốn thay đổi chỉ mục một cách không cần thiết khi thêm cột trừ khi đó là một mục tiêu rõ ràng ...
Acumenus

1
.reindex()được sử dụng với columnsđối số, vì vậy nó chỉ thay đổi cột "chỉ mục" (tên). Nó không làm thay đổi chỉ mục hàng.
Matthias Fripp

đối với một số cách tiếp cận, bạn có thể sử dụng OrderedDict: ví dụ:df.join(pd.DataFrame( OrderedDict([('column_new_2', 'dogs'),('column_new_1', np.nan),('column_new_3', 3)]), index=df.index ))
hashmuke

@hashmuke Điều đó có ý nghĩa đối với các phiên bản đầu tiên của Python. Nó có thể thu hút đặc biệt đối với những người sử dụng từ điển cho nhiều thứ trong Gấu trúc, ví dụ: df = pd.DataFrame({'before': [1, 2, 3], 'after': [4, 5, 6]})vs.df = pd.DataFrame(OrderedDict([('before', [1, 2, 3]), ('after', [4, 5, 6])])
Matthias Fripp

2
Trong trường hợp bạn đang sử dụng tùy chọn với join, hãy đảm bảo rằng bạn không có các bản sao trong chỉ mục của mình (hoặc sử dụng tùy chọn reset_indexđầu tiên). Có thể giúp bạn tiết kiệm vài giờ gỡ lỗi.
Guido

40

Bạn có thể sử dụng assignvới một chính tả của các tên và giá trị cột.

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

Có cách nào làm tương tự để duy trì thứ tự cụ thể của các cột không?
user48956,

1
Bạn có thể duy trì một thứ tự cụ thể với các phiên bản Python trước đó bằng cách gọi gán nhiều lần: df.assign(**{'col_new_1': np.nan}).assign(**{'col2_new_2': 'dogs'}).assign(**{'col3_new_3': 3})
skasch

9

Với việc sử dụng 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

Không chắc chắn về những gì bạn muốn làm với [np.nan, 'dogs',3]. Có thể bây giờ đặt chúng làm giá trị mặc định?

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

nếu có một cách để thực hiện phần thứ hai của bạn trong một bước - có các giá trị không đổi trong các cột làm ví dụ.
runningbirds

3

sử dụng khả năng hiểu danh sách pd.DataFramepd.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)

nhập mô tả hình ảnh ở đây


3

nếu thêm nhiều cột bị thiếu (a, b, c, ....) có cùng giá trị, ở đây 0, tôi đã làm điều này:

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

Nó dựa trên biến thể thứ hai của câu trả lời được chấp nhận.


0

Chỉ muốn chỉ ra phương án 2 đó trong câu trả lời của @Matthias Fripp

(2) Tôi không nhất thiết phải mong đợi DataFrame hoạt động theo cách này, nhưng nó có

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

đã được ghi lại trong tài liệu riêng của gấu trúc http://pandas.pydata.org/pandas-docs/stable/indexing.html#basics

Bạn có thể chuyển danh sách các cột cho [] để chọn các cột theo thứ tự đó. Nếu một cột không được chứa trong DataFrame, một ngoại lệ sẽ được đưa ra. Nhiều cột cũng có thể được đặt theo cách này. Bạn có thể thấy điều này hữu ích khi áp dụng một phép biến đổi ( tại chỗ ) cho một tập hợp con của các cột.


Tôi nghĩ đây là tiêu chuẩn khá tốt cho việc gán nhiều cột. Phần làm tôi ngạc nhiên là pd.DataFrame([[np.nan, 'dogs', 3]], index=df.index)sao chép một hàng mà nó được đưa ra để tạo toàn bộ khung dữ liệu có cùng độ dài với chỉ mục.
Matthias Fripp

0

Nếu bạn chỉ muốn thêm các cột mới trống, reindex sẽ thực hiện công việc

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

mã đầy đủ ví dụ

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')

nếu không thì đi cho câu trả lời số không với gán


0

Tôi không thoải mái khi sử dụng "Chỉ mục", v.v. ... có thể đưa ra như bên dưới

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')
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.