将具有恒定值的列添加到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 2014年

5
同样,这里完全不需要列表理解。只是做[0] * len(df.index)
acushner 2014年

@joris,我的意思是df ['new'] = 0显示了为什么向整个列分配零的正确原因,但是并不能解释为什么我第一次尝试插入NaN的原因。菲利普·乌克(Philip Cloud)在我接受的答案中回答了这一问题。
yemu 2014年

7
只需做df['new'] = 0
一下

Answers:


21

之所以将其NaN放入一列中,是因为df.indexIndex您右侧对象的有所不同。@zach显示了分配新的零列的正确方法。通常,pandas尝试尽可能使索引对齐。一个缺点是,当指数不对准你NaN,无论他们是不是一致。尝试使用reindexalign方法来获得一些直觉,以便对齐具有部分,完全和未对齐所有对齐索引的对象。例如,以下是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

我不同意这里只有一个问题。有“如何为列分配常量值?” 以及“我的尝试无法以X方式运行,为什么行为异常?” 我相信我已经解决了这两点,第一点是参考另一个答案。请阅读我的答案中的所有文字。
菲利普·

我认为问题出在问题而不是答案。这篇文章中包含两个不同的问题,因此需要两个不同的答案才能回答该问题。我认为这应该被标记为范围太广,而发帖人应该问两个单独的问题。
凯文(Kevin)

81

超简单的就地分配: 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

我认为Phillip Cloud的答案已经过时。cs95的答案对我来说似乎是正确的,但它使IMO变得有些复杂。这是一种更简单的方法。至少对于所提出的问题。
Roko Mijic

1
Fyi此答案与cs95(又名我)答案之间的唯一区别是列名和值。所有的东西都在那里。
cs95

1
它们的过时并不是很多,但是这个答案比其他答案更冗长,更易于阅读。
乔伊

@Joey不能用这种逻辑来争论,我想这个答案更适合那些只想复制粘贴任何可以使用的东西,而不是想要了解和学习更多有关该库的人。感动。
cs95

7

这是另一种使用lambdas的班轮(创建常数值为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也是一个衬板(并且速度更快)。在这里使用Apply的好处是什么?
cs95

2
在这里不尝试与您竞争-只是显示一种替代方法。
Grant Shannon

@ cs95这很有帮助。我想创建一个新列,其中每个值都是一个单独的空列表。仅此方法有效。
Yatharth Agarwal

@YatharthAgarwal我会给你的,但是鉴于熊猫的设计目的不是要与列表的列配合使用,这也很有意义。
cs95 8:51

1
@YatharthAgarwal如果您需要分配空列表,由于它使用apply,因此它仍然是一个低于标准的解决方案。试试df['new'] = [[] for _ in range(len(df))]
cs95
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.