Як додати декілька стовпців до кадру даних панд в одному призначенні?


122

Я новачок у пандах і намагаюся зрозуміти, як додати декілька стовпців до панд одночасно. Будь-яка допомога тут цінується. В ідеалі я хотів би зробити це одним кроком, а не декількома повторними кроками ...

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

Вам потрібно вказати, яка помилка ви отримали. Коли я спробую це на KeyError: "None of [Index(['column_new_1', 'column_new_2', 'column_new_3'], dtype='object')] are in the [columns]"
пандах

Відповіді:


185

Я б очікував, що і ваш синтаксис також спрацює. Проблема виникає через те, що при створенні нових стовпців із синтаксисом списку стовпців ( 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 є більш "природним" способом створення нового кадру даних, ніж попередні два, але нові стовпці будуть сортовані за алфавітом (принаймні перед 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()з кількома аргументами стовпців.

Мені дуже подобається цей варіант у відповіді @ нуля, але, як і в попередньому, нові стовпці завжди будуть відсортовані за алфавітом, принаймні з ранніми версіями 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аргументом, тому він змінює лише стовпець "індекс" (імена). Це не змінює індекс рядка.
Маттіас Фріпп

для деяких підходів ви можете використовувати OrderedDict: наприклад,df.join(pd.DataFrame( OrderedDict([('column_new_2', 'dogs'),('column_new_1', np.nan),('column_new_3', 3)]), index=df.index ))
hashmuke

@hashmuke Це має сенс для ранніх версій Python. Особливо це може сподобатись людям, які використовують словники для кількох речей у Пандах, наприклад, df = pd.DataFrame({'before': [1, 2, 3], 'after': [4, 5, 6]})протиdf = pd.DataFrame(OrderedDict([('before', [1, 2, 3]), ('after', [4, 5, 6])])
Маттіас Фріпп,

2
Якщо ви використовуєте параметр з join, переконайтеся, що у вашому індексі немає дублікатів (або використовуйте reset_indexперший). Можливо, ви заощадите кілька годин налагодження.
Гвідо

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

1
Ви можете підтримувати певне замовлення з більш ранніми версіями Python, зателефонувавши присвоїти кілька разів: df.assign(**{'col_new_1': np.nan}).assign(**{'col2_new_2': 'dogs'}).assign(**{'col3_new_3': 3})
skasch

9

З використанням конмат :

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

якщо був спосіб виконати свою другу частину за один крок - так, постійні значення в стовпцях як приклад.
runbirds

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

Просто хочу зазначити, що варіант2 у відповіді @Matthias Fripp

(2) Я не обов'язково очікую, що DataFrame працює таким чином, але це так

df [['column_new_1', 'column_new_2', 'column_new_3']] = pd.DataFrame ([[np.nan, 'собаки', 3]], індекс = df.index)

вже задокументовано у власній документації панд http://pandas.pydata.org/pandas-docs/stable/indexing.html#basics

Ви можете передати список стовпців до [], щоб вибрати стовпці в такому порядку. Якщо стовпчик не міститься у DataFrame, буде зроблено виняток. Кілька стовпців також можна встановити таким чином. Це може бути корисним для застосування перетворення ( на місці ) до підмножини стовпців.


Я думаю, що це досить стандартно для багатоступеневого призначення. Мене здивувало те, що pd.DataFrame([[np.nan, 'dogs', 3]], index=df.index)реплікує один рядок, який йому надається, щоб створити цілий фрейм даних такої ж довжини, як і індекс.
Маттіас Фріпп

0

Якщо ви просто хочете додати порожні нові стовпці, reindex зробить цю роботу

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')
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.