Додавання стовпця з постійним значенням до фрейму даних pandas [дублікат]


102

Дано 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
також розуміння списку тут зовсім непотрібне. just do[0] * len(df.index)
acushner

@joris, я мав на увазі, що df ['new'] = 0 показує правильну причину призначення нулів цілому стовпцю, але це не пояснює, чому моя перша спроба вставляє NaN. На це відповів Філіп Хмара у відповіді, яку я прийняв.
yemu

7
Просто зробітьdf['new'] = 0
flow2k

Відповіді:


21

Причина, яку це поміщає 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

9
я не проголосував проти, але у вашому коді не вистачає коментарів, ускладнює його виконання разом з тим, що ви намагаєтесь досягти у фрагменті
відшкодування

8
Це насправді не відповідає на питання. OP запитує про те, як додати новий стовпець, що містить постійне значення.
cs95

Я не згоден, що тут є лише одне питання. Там "Як мені призначити константу значення стовпцю?" а також "Моя спроба зробити це не працює по-іншому, чому вона поводиться несподівано?" Я вважаю, що я звернувся до обох пунктів, перший, посилаючись на іншу відповідь. Будь ласка, прочитайте весь текст у моїй відповіді.
Філіп Хмара,

Я думаю, що проблема полягає не в вашій відповіді, а в питанні. У цій публікації є два окремі запитання, і в результаті для відповіді на це запитання потрібні дві різні відповіді. Я вважаю, що це слід було позначити як занадто широке, а плакат повинен був задати два окремі питання.
Кевін

82

Супер просте призначення на місці: 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

17

За допомогою сучасних панд ви можете просто зробити:

df['new'] = 0

1
Чи можете ви вказати, які конкретні відповіді застаріли? Залишимо коментар під ними, щоб автори мали можливість покращитися.
cs95

1
Fyi Єдина різниця між цією відповіддю та відповіддю cs95 (AKA, я) - це назва стовпця та значення. Всі шматки є там.
cs95

1
Справа не стільки в тому, що вони застаріли, але ця відповідь є менш багатослівною, ніж інші, і її легше прочитати.
Джої

1
@Joey Не можу посперечатися з цією логікою, я вважаю, що ця відповідь більше підходить людям, які просто хочуть скопіювати все, що працює, а не зрозуміти і дізнатись більше про бібліотеку. Туш.
cs95

1
@ cs95 так, ваша відповідь дозволяє людям дізнатися більше. Також df ['new'] = 0, виділене в заголовку, добре для читабельності. Я також підтримав це. Менш багатослівно, ніж df.apply (лямбда x: 0, вісь = 1)
Джої

7

Ось ще один лайнер із використанням лямбда (створити стовпець із постійним значенням = 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
не намагаючись конкурувати з вами тут - лише демонструючи альтернативний підхід.
Грант Шеннон,

@ cs95 Це корисно. Я хотів створити новий стовпець, де кожне значення було б окремим порожнім списком. Працює лише цей метод.
Ятхарт Агарвал,

@YatharthAgarwal Я вам це дам, але це також має сенс, оскільки панди не створені для хорошої роботи зі стовпцями списків.
cs95

1
@YatharthAgarwal Якщо вам потрібно призначити порожні списки, це все ще є допоміжним рішенням, оскільки воно використовує apply. Спробуйтеdf['new'] = [[] for _ in range(len(df))]
cs95
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.