【问题标题】:Add column with constant value to pandas dataframe [duplicate]将具有常量值的列添加到熊猫数据框[重复]
【发布时间】:2022-01-08 23:42:16
【问题描述】:

给定一个数据框:

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

【问题讨论】:

  • 如果你使用索引没问题。 df['new'] = pd.Series([0 for x in range(len(df.index))], index=df.index).
  • 另外,这里完全不需要列表理解。就做[0] * len(df.index)
  • @joris,我的意思是 df['new']=0 显示了为整个列分配零的正确原因,但它没有解释为什么我的第一次尝试插入 NaN。 Philip Cloud 在我接受的答案中回答了这个问题。
  • 只需做df['new'] = 0

标签: python pandas


【解决方案1】:

之所以将NaN 放入一列是因为df.index 和您右侧对象的Index 不同。 @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

【讨论】:

  • 我没有投反对票,但您的代码缺少 cmets,因此很难遵循您在 sn-p 中尝试实现的目标
  • 这并不能真正回答问题。 OP 正在询问如何添加包含常量值的新列。
  • 我不同意这里只有一个问题。有“如何为列分配常量值?”以及“我这样做的尝试在 X 方式下不起作用,为什么它的行为出乎意料?”我相信我已经解决了这两点,第一点是参考另一个答案。请阅读我回答中的所有文本。
  • 我认为问题在于问题而不是您的答案。这篇文章包含两个不同的问题,因此需要两个不同的答案来回答这个问题。我认为这应该被标记为过于宽泛,发帖人应该问两个不同的问题。
【解决方案2】:

超级简单的就地赋值:df['new'] = 0

对于就地修改,执行直接分配。这个作业由 pandas 为每一行广播。

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 列在性能方面是个坏消息。重新思考数据的结构。
  • 考虑将数据存储在稀疏数据结构中。更多信息:sparse data structures
  • 如果您必须存储一列列表,请确保不要多次复制相同的引用。

    # 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

【讨论】:

    【解决方案3】:

    这是另一个使用 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
    

    【讨论】:

    • df['newCol'] = 10 也是单线(并且速度更快)。在这里使用 apply 有什么好处?
    • 不想在这里与您竞争 - 只是展示另一种方法。
    • @cs95 这很有帮助。我想创建一个新列,其中每个值都是一个单独的空列表。只有这种方法有效。
    • @YatharthAgarwal 如果您需要分配空列表,这仍然是一个低于标准的解决方案,因为它使用 apply。试试df['new'] = [[] for _ in range(len(df))]
    • 我更喜欢这种解决方案,适合像我这样的初学者。 df.apply 函数可用于解决各种问题,并且此用例具有意义。另一方面,df['newCol'] = 10 易于使用并且“神奇”地工作,它具有很大的逻辑意义,并且是人们需要从心开始学习的东西。
    【解决方案4】:

    使用现代熊猫,您可以这样做:

    df['new'] = 0
    

    【讨论】:

    • 你能指出哪些具体答案已经过时了吗?让我们在它们下面留下评论,以便作者有机会改进。
    • 仅供参考,此答案与 cs95(AKA,我)答案之间的唯一区别是列名和值。所有的碎片都在那里。
    • 与其说它们已经过时了,不如说这个答案比其他答案更简洁,更易于阅读。
    • @Joey 无法反驳这种逻辑,我想这个答案更适合那些只想复制粘贴任何可行的东西,而不是想了解和了解更多关于图书馆的人.触摸。
    • @cs95 是的,您的回答可以让人们了解更多信息。标题中突出显示的 df['new'] = 0 也有利于可读性。我也对此表示赞同。比 df.apply(lambda x: 0, axis=1) 更简洁
    猜你喜欢
    • 2018-10-14
    • 2017-08-21
    • 1970-01-01
    • 2016-08-17
    • 2018-12-14
    • 2023-02-09
    • 2021-12-18
    • 2016-09-08
    相关资源
    最近更新 更多