Добавить столбец с постоянным значением в фреймворк 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
Кроме того, здесь нет необходимости в понимании списка. [0] * len(df.index)
Just
@joris, я имел в виду, что df ['new'] = 0 показывает правильную причину присвоения нулей всему столбцу, но не объясняет, почему моя первая попытка вставляет NaN. На это ответил Филип Клауд в принятом мной ответе.
yemu 04
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
Филипп Клауд
источник
10
Я не голосовал против, но в вашем коде нет комментариев, из-за чего трудно следовать тому, чего вы пытаетесь достичь во фрагменте
исправить
8
Это не совсем ответ на вопрос. OP спрашивает, как добавить новый столбец, содержащий постоянное значение.
cs95
Я не согласен, что здесь есть только один вопрос. Там «Как мне присвоить постоянное значение столбцу?» а также "Моя попытка сделать это не работает в X, почему он ведет себя неожиданно?" Я считаю, что рассмотрел оба пункта, первый, сославшись на другой ответ. Пожалуйста, прочтите весь текст моего ответа.
Филлип Клауд
Думаю, проблема скорее в вопросе, чем в вашем ответе. В этом посте содержатся два разных вопроса, поэтому для ответа на них требуется два разных ответа. Я считаю, что это должно было быть отмечено как слишком широкое, и на плакате следовало задать два отдельных вопроса.
Кевин
83

Супер простое назначение на месте: 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
cs95
источник
18

С современными пандами вы можете просто:

df['new'] = 0
Роко Мижич
источник
1
Можете ли вы указать, какие именно ответы устарели? Давайте оставим под ними комментарий, чтобы у авторов была возможность стать лучше.
cs95
1
Fyi, единственная разница между этим ответом и ответом cs95 (AKA, me) - это имя и значение столбца. Все части есть.
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 Это полезно. Я хотел создать новый столбец, в котором каждое значение представляло собой отдельный пустой список. Только этот метод работает.
Yatharth Agarwal
@YatharthAgarwal Я дам вам это, но это также имеет смысл, учитывая, что pandas не предназначен для работы со столбцами списков.
cs95
1
@YatharthAgarwal Если вам нужно назначить пустые списки, это все еще некачественное решение, потому что оно использует apply. Попробуйтеdf['new'] = [[] for _ in range(len(df))]
cs95