问答中心分类: DATABASE如何向现有 DataFrame 添加新列?
0
匿名用户 提问 5分钟 前

我有以下索引DataFrame,其中命名的列和行不是连续的数字:

a         b         c         d
2  0.671399  0.101208 -0.181532  0.241273
3  0.446172 -0.243316  0.051767  1.577318
5  0.614758  0.075793 -0.451460 -0.012493

我想添加一个新列,'e', 到现有数据框并且不想更改数据框中的任何内容(即,新列始终与 DataFrame 具有相同的长度)。

0   -0.335485
1   -1.166658
2   -0.385571
dtype: float64

如何添加列e到上面的例子?

Ersin Gulbahar 回复 5分钟 前

如果您的新列依赖于您现有的列,那么您可以在下面添加新列。

Ersin Gulbahar 回复 5分钟 前

哇,这个问答真是一团糟。直截了当的答案是df['e'] = e,但是如果索引不匹配,那将不起作用,但是索引不匹配,因为OP这样创建它(e = Series(<np_array>)),但这已从修订版 5 的问题中删除。

29 Answers
0
Kathirmani Sukumar 回答 5分钟 前

这是添加新列的简单方法:df['e'] = e

joaquin 回复 5分钟 前

尽管票数很高:这个答案是错误的.请注意,OP 有一个带有非连续索引的数据框,并且e(Series(np.random.randn(sLength))) 生成一个系列 0-n 索引。如果你把它分配给 df1 那么你会得到一些 NaN 单元格。

VedTopkar 回复 5分钟 前

@joaquin 说的是真的,但只要你牢记这一点,这是一个非常有用的捷径。

Kathirmani Sukumar 回复 5分钟 前

@Eric Leschinski:不确定您如何编辑对这个问题有帮助。my_dataframe = pd.DataFrame(columns=('foo', 'bar')).还原您的编辑

Paniz 回复 5分钟 前

它没有帮助,因为如果您有多行并且您使用分配,它会为新列的所有行分配该值(在您的情况下为 e),这通常是不受欢迎的。

flow2k 回复 5分钟 前

上面提出的@joaquin 问题可以通过以下方式简单地解决(如上面的 joaquin 的回答):df['e'] = e.values或等效地,df['e'] = e.to_numpy().正确的?

flow2k 回复 5分钟 前

我在 DataFrame API 参考中没有找到这种语法,但它在官方 Pandas 用户指南中使用:pandas.pydata.org/docs/user_guide/…

mirekphd 回复 5分钟 前

注意:高否决票率(现在为 1/6)(使用df['e'] = e.values反而)

Shashi Shekhar 回复 5分钟 前

它对我有帮助!

0
Alexander 回答 5分钟 前

我想在现有数据框中添加一个新列“e”,并且不要更改数据框中的任何内容。 (该系列的长度始终与数据框相同。)

我假设索引值在e匹配那些在df1.
启动名为的新列的最简单方法e, 并为其分配您的系列中的值e

df['e'] = e.values

分配(熊猫 0.16.0+)
从 Pandas 0.16.0 开始,您还可以使用assign,它将新列分配给 DataFrame 并返回一个新对象(副本),其中包含除新列之外的所有原始列。

df1 = df1.assign(e=e.values)

按照这个例子(其中还包括源代码assign函数),您还可以包含多个列:

df = pd.DataFrame({'a': [1, 2], 'b': [3, 4]})
>>> df.assign(mean_a=df.a.mean(), mean_b=df.b.mean())
   a  b  mean_a  mean_b
0  1  3     1.5     3.5
1  2  4     1.5     3.5

在您的示例中:

np.random.seed(0)
df1 = pd.DataFrame(np.random.randn(10, 4), columns=['a', 'b', 'c', 'd'])
mask = df1.applymap(lambda x: x <-0.7)
df1 = df1[-mask.any(axis=1)]
sLength = len(df1['a'])
e = pd.Series(np.random.randn(sLength))

>>> df1
          a         b         c         d
0  1.764052  0.400157  0.978738  2.240893
2 -0.103219  0.410599  0.144044  1.454274
3  0.761038  0.121675  0.443863  0.333674
7  1.532779  1.469359  0.154947  0.378163
9  1.230291  1.202380 -0.387327 -0.302303

>>> e
0   -1.048553
1   -1.420018
2   -1.706270
3    1.950775
4   -0.509652
dtype: float64

df1 = df1.assign(e=e.values)

>>> df1
          a         b         c         d         e
0  1.764052  0.400157  0.978738  2.240893 -1.048553
2 -0.103219  0.410599  0.144044  1.454274 -1.420018
3  0.761038  0.121675  0.443863  0.333674 -1.706270
7  1.532779  1.469359  0.154947  0.378163  1.950775
9  1.230291  1.202380 -0.387327 -0.302303 -0.509652

可以找到该新功能首次引入时的描述这里.

Eike P. 回复 5分钟 前

考虑到第一种方法(df['e'] = e.values) 不会创建数据框的副本,而第二个选项(使用df.assign) 做?在顺序添加大量新列和大型数据框的情况下,我希望第一种方法的性能更好。

Alexander 回复 5分钟 前

@jhin 是的,如果您正在处理固定数据框,那么直接分配显然很多。使用的好处assign是将您的操作链接在一起的时候。

Abe Hoffman 回复 5分钟 前

这似乎是显式和隐式之间的一个很好的平衡。 +1:D

piRSquared 回复 5分钟 前

为了娱乐df.assign(**df.mean().add_prefix('mean_'))

Rodolfo Alvarez 回复 5分钟 前

只是为了更新这个答案版本 v0.23.2assign“总是返回数据的副本,而原始 DataFrame 保持不变。”

Owlright 回复 5分钟 前

您“假设 e 中的索引值与 df1 中的索引值匹配”。如果索引值不匹配怎么办?

Alexander 回复 5分钟 前

@Owlright从问题来看,OP似乎只是连接数据帧并忽略索引。如果是这种情况,上述方法将起作用。如果希望保留索引,请使用类似df_new = pd.concat([df1, df2], axis=1),注意到ignore_index=False默认。

frankliuao 回复 5分钟 前

assign()是很棒的。我相信现在直接使用索引分配会发出警告。

0
firelynx 回答 5分钟 前

超级简单的列分配
pandas 数据框被实现为列的有序字典。
这意味着__getitem__ []不仅可以用来获取某一列,而且__setitem__ [] =可用于分配新列。
例如,这个数据框可以通过简单地使用[]存取器

size      name color
0    big      rose   red
1  small    violet  blue
2  small     tulip   red
3  small  harebell  blue

df['protected'] = ['no', 'no', 'no', 'yes']

    size      name color protected
0    big      rose   red        no
1  small    violet  blue        no
2  small     tulip   red        no
3  small  harebell  blue       yes

请注意,即使数据帧的索引关闭,这也有效。

df.index = [3,2,1,0]
df['protected'] = ['no', 'no', 'no', 'yes']
    size      name color protected
3    big      rose   red        no
2  small    violet  blue        no
1  small     tulip   red        no
0  small  harebell  blue       yes

[]= 是要走的路,但要小心!
但是,如果您有一个pd.Series并尝试将其分配给索引关闭的数据框,您将遇到麻烦。参见示例:

df['protected'] = pd.Series(['no', 'no', 'no', 'yes'])
    size      name color protected
3    big      rose   red       yes
2  small    violet  blue        no
1  small     tulip   red        no
0  small  harebell  blue        no

这是因为一个pd.Series默认情况下有一个从 0 到 n 枚举的索引。还有熊猫[] =方法尝试 变聪明”
究竟发生了什么。
当您使用[] =方法 pandas 正在使用左侧数据帧的索引和右侧系列的索引悄悄地执行外部连接或外部合并。df['column'] = series
边注
这很快导致认知失调,因为[]=方法是根据输入尝试做很多不同的事情,结果无法预测,除非你只知道熊猫是如何工作的。因此,我建议反对[]=在代码库中,但在笔记本中探索数据时,这很好。
绕过问题
如果你有一个pd.Series并希望它从上到下分配,或者如果您正在编写生产代码并且您不确定索引顺序,那么为此类问题进行维护是值得的。
你可以失望pd.Series到一个np.ndarray或一个list,这样就可以了。

df['protected'] = pd.Series(['no', 'no', 'no', 'yes']).values

或者

df['protected'] = list(pd.Series(['no', 'no', 'no', 'yes']))

但这不是很明确。
一些编码员可能会说“嘿,这看起来多余,我会优化它”。
显式方式
设置索引pd.Series成为索引df是明确的。

df['protected'] = pd.Series(['no', 'no', 'no', 'yes'], index=df.index)

或者更现实地说,你可能有一个pd.Series已经可用。

protected_series = pd.Series(['no', 'no', 'no', 'yes'])
protected_series.index = df.index

3     no
2     no
1     no
0    yes

现在可以分配

df['protected'] = protected_series

    size      name color protected
3    big      rose   red        no
2  small    violet  blue        no
1  small     tulip   red        no
0  small  harebell  blue       yes

替代方式df.reset_index()
由于索引不协调是问题,如果您觉得数据框的索引应该不是规定的事情,你可以简单地删除索引,这应该更快,但它不是很干净,因为你的函数现在大概做两件事。

df.reset_index(drop=True)
protected_series.reset_index(drop=True)
df['protected'] = protected_series

    size      name color protected
0    big      rose   red        no
1  small    violet  blue        no
2  small     tulip   red        no
3  small  harebell  blue       yes

注意事项df.assign
尽管df.assign让它更明确你在做什么,它实际上有与上述相同的问题[]=

df.assign(protected=pd.Series(['no', 'no', 'no', 'yes']))
    size      name color protected
3    big      rose   red       yes
2  small    violet  blue        no
1  small     tulip   red        no
0  small  harebell  blue        no

请注意df.assign你的专栏没有被调用self.它会导致错误。这使得df.assign ,因为函数中有这类伪影。

df.assign(self=pd.Series(['no', 'no', 'no', 'yes'])
TypeError: assign() got multiple values for keyword argument 'self'

你可能会说,“好吧,我只是不使用self然后”。但是谁知道这个函数将来会如何改变以支持新的参数。也许你的列名将成为熊猫新更新中的参数,导致升级出现问题。

Lightman 回复 5分钟 前

当您使用[] =方法 pandas 正在悄悄地执行外部连接或外部合并“。这是整个主题中最重要的信息。但是您能否提供官方文档的链接以了解如何[]=运营商工作?

0
Mikhail Korobov 回答 5分钟 前

似乎在最近的 Pandas 版本中,要走的路是使用df.assign
df1 = df1.assign(e=np.random.randn(sLength))
它不产生SettingWithCopyWarning.

Kyle C 回复 5分钟 前

从上面复制@smci 的评论……不要说“当前”或参考年份,请参考 Pandas 版本号

0
Andy Hayden 回答 5分钟 前

直接通过数字货币将是最有效的:

df1['e'] = np.random.randn(sLength)

请注意,我最初的(非常旧的)建议是使用map(这要慢得多):

df1['e'] = df1['a'].map(lambda x: np.random.random())
tomasz74 回复 5分钟 前

感谢您的回复,正如我已经给出的那样,我可以修改您的代码吗?.map使用现有系列而不是lambda?我试试df1['e'] = df1['a'].map(lambda x: e)或者df1['e'] = df1['a'].map(e)但这不是我需要的。 (我是pyhon的新手,你之前的回答已经帮助了我)

Andy Hayden 回复 5分钟 前

@tomasz74 如果你已经有e作为一个系列,那么你不需要使用map, 利用df['e']=e(@joaquins 回答)。