我有以下索引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添加到上面的例子中?


当前回答

向现有数据框架添加新列的简单方法是:

new_cols = ['a' , 'b' , 'c' , 'd']

for col in new_cols:
    df[f'{col}'] = 0 #assiging 0 for the placeholder

print(df.columns)

其他回答

要在数据帧的给定位置(0 <= loc <=列的数量)插入一个新列,只需使用datafframe .insert:

DataFrame.insert(loc, column, value)

因此,如果你想在一个名为df的数据帧的末尾添加列e,你可以使用:

e = [-0.335485, -1.166658, -0.385571]    
DataFrame.insert(loc=len(df.columns), column='e', value=e)

value可以是一个Series,一个整数(在这种情况下,所有单元格都被这个值填充),或者一个类似数组的结构

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.insert.html

超级简单的列赋值

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。如果您试图将其分配给一个索引关闭的数据框架,那么您将遇到麻烦。看到的例子:

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。默认情况下,系列具有从0到n的枚举索引。pandas[] =方法试图“聪明”

到底发生了什么。

当您使用[]=方法时,pandas使用左手数据框架的索引和右手系列的索引悄悄执行外部连接或外部合并。Df ['column'] =级数

边注

这很快就会导致认知失调,因为[]=方法试图根据输入做很多不同的事情,除非您只知道pandas是如何工作的,否则无法预测结果。因此,我建议不要在代码库中使用[]=,但在笔记本中查看数据时,使用[]=是可以的。

绕过问题

如果你有警察。系列,并希望它从上到下分配,或者如果您正在编码生产代码,而您不确定索引顺序,那么值得为这种问题进行保护。

你可以让警察失望。级数到np。Ndarray或一个列表,这将达到目的。

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

or

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

但这并不是很明确。

有些程序员可能会说:“嘿,这看起来有点多余,我就把它优化掉吧。”

明确的方法

设置pd的索引。作为df下标的级数是明确的。

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

或者更现实一点,你可能有个警察。系列已经可用。

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。赋值让它更明确你在做什么,它实际上有和上面[]=相同的问题

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。指定你的列不叫self。这会导致错误。这就得到df。Assign smell,因为函数中存在这类工件。

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

你可能会说,那我就不用self了。但是谁知道这个函数将来会如何改变来支持新的论点呢。也许您的列名将在pandas的新更新中成为一个参数,从而导致升级出现问题。

我得到了可怕的SettingWithCopyWarning,它没有通过使用iloc语法修复。我的DataFrame是由read_sql从ODBC源创建的。根据上面low - tech的建议,以下方法对我来说是有效的:

df.insert(len(df.columns), 'e', pd.Series(np.random.randn(sLength),  index=df.index))

This worked fine to insert the column at the end. I don't know if it is the most efficient, but I don't like warning messages. I think there is a better solution, but I can't find it, and I think it depends on some aspect of the index. Note. That this only works once and will give an error message if trying to overwrite and existing column. Note As above and from 0.16.0 assign is the best solution. See documentation http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.assign.html#pandas.DataFrame.assign Works well for data flow type where you don't overwrite your intermediate values.

如果你想将整个新列设置为一个初始值(例如None),你可以这样做:df1['e'] = None

这实际上会给单元格分配object类型。因此,稍后您可以自由地将复杂的数据类型(如列表)放入单个单元格中。

import pandas as pd

# Define a dictionary containing data
data = {'a': [0,0,0.671399,0.446172,0,0.614758],
    'b': [0,0,0.101208,-0.243316,0,0.075793],
    'c': [0,0,-0.181532,0.051767,0,-0.451460],
    'd': [0,0,0.241273,1.577318,0,-0.012493]}

# Convert the dictionary into DataFrame
df = pd.DataFrame(data)

# Declare a list that is to be converted into a column
col_e = [-0.335485,-1.166658,-0.385571,0,0,0]


df['e'] = col_e

# add column 'e'
df['e'] = col_e

# Observe the result
df