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


当前回答

向pandas数据框架插入新列的4种方法

using simple assignment, insert(), assign() and Concat() methods.

import pandas as pd

df = pd.DataFrame({
    'col_a':[True, False, False], 
    'col_b': [1, 2, 3],
})
print(df)
    col_a  col_b
0   True     1
1  False     2
2  False     3

使用简单赋值

ser = pd.Series(['a', 'b', 'c'], index=[0, 1, 2])
print(ser)
0    a
1    b
2    c
dtype: object

df['col_c'] = pd.Series(['a', 'b', 'c'], index=[1, 2, 3])
print(df)
     col_a  col_b col_c
0   True     1  NaN
1  False     2    a
2  False     3    b

使用分配()

e = pd.Series([1.0, 3.0, 2.0], index=[0, 2, 1])
ser = pd.Series(['a', 'b', 'c'], index=[0, 1, 2])
df.assign(colC=s.values, colB=e.values)
     col_a  col_b col_c
0   True   1.0    a
1  False   3.0    b
2  False   2.0    c

使用insert ()

df.insert(len(df.columns), 'col_c', ser.values)
print(df)
    col_a  col_b col_c
0   True     1    a
1  False     2    b
2  False     3    c

使用concat ()

ser = pd.Series(['a', 'b', 'c'], index=[10, 20, 30])
df = pd.concat([df, ser.rename('colC')], axis=1)
print(df)
     col_a  col_b col_c
0    True   1.0  NaN
1   False   2.0  NaN
2   False   3.0  NaN
10    NaN   NaN    a
20    NaN   NaN    b
30    NaN   NaN    c

其他回答

直接通过NumPy这样做将是最有效的:

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

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

df1['e'] = df1['a'].map(lambda x: np.random.random())

为了完整起见-使用DataFrame.eval()方法的另一个解决方案:

数据:

In [44]: e
Out[44]:
0    1.225506
1   -1.033944
2   -0.498953
3   -0.373332
4    0.615030
5   -0.622436
dtype: float64

In [45]: df1
Out[45]:
          a         b         c         d
0 -0.634222 -0.103264  0.745069  0.801288
4  0.782387 -0.090279  0.757662 -0.602408
5 -0.117456  2.124496  1.057301  0.765466
7  0.767532  0.104304 -0.586850  1.051297
8 -0.103272  0.958334  1.163092  1.182315
9 -0.616254  0.296678 -0.112027  0.679112

解决方案:

In [46]: df1.eval("e = @e.values", inplace=True)

In [47]: df1
Out[47]:
          a         b         c         d         e
0 -0.634222 -0.103264  0.745069  0.801288  1.225506
4  0.782387 -0.090279  0.757662 -0.602408 -1.033944
5 -0.117456  2.124496  1.057301  0.765466 -0.498953
7  0.767532  0.104304 -0.586850  1.051297 -0.373332
8 -0.103272  0.958334  1.163092  1.182315  0.615030
9 -0.616254  0.296678 -0.112027  0.679112 -0.622436

如果数据帧和Series对象具有相同的索引,则为pandas。Concat也在这里工作:

import pandas as pd
df
#          a            b           c           d
#0  0.671399     0.101208   -0.181532    0.241273
#1  0.446172    -0.243316    0.051767    1.577318
#2  0.614758     0.075793   -0.451460   -0.012493

e = pd.Series([-0.335485, -1.166658, -0.385571])    
e
#0   -0.335485
#1   -1.166658
#2   -0.385571
#dtype: float64

# here we need to give the series object a name which converts to the new  column name 
# in the result
df = pd.concat([df, e.rename("e")], axis=1)
df

#          a            b           c           d           e
#0  0.671399     0.101208   -0.181532    0.241273   -0.335485
#1  0.446172    -0.243316    0.051767    1.577318   -1.166658
#2  0.614758     0.075793   -0.451460   -0.012493   -0.385571

以防它们没有相同的索引:

e.index = df.index
df = pd.concat([df, e.rename("e")], axis=1)

你可以像这样通过for循环插入新列:

for label,row in your_dframe.iterrows():
      your_dframe.loc[label,"new_column_length"]=len(row["any_of_column_in_your_dframe"])

示例代码如下:

import pandas as pd

data = {
  "any_of_column_in_your_dframe" : ["ersingulbahar","yagiz","TS"],
  "calories": [420, 380, 390],
  "duration": [50, 40, 45]
}

#load data into a DataFrame object:
your_dframe = pd.DataFrame(data)


for label,row in your_dframe.iterrows():
      your_dframe.loc[label,"new_column_length"]=len(row["any_of_column_in_your_dframe"])
      
      
print(your_dframe) 

输出如下:

any_of_column_in_your_dframe calories duration new_column_length
ersingulbahar 420 50 13.0
yagiz 380 40 5.0
TS 390 45 2.0

你也可以这样用:

your_dframe["new_column_length"]=your_dframe["any_of_column_in_your_dframe"].apply(len)

编辑2017

正如@Alexander在评论中所指出的,目前将Series的值添加为DataFrame的新列的最好方法是使用assign:

df1 = df1.assign(e=pd.Series(np.random.randn(sLength)).values)

编辑2015 有些人报告说用这段代码得到了SettingWithCopyWarning。 但是,该代码仍然可以在当前的pandas版本0.16.1中完美运行。

>>> sLength = len(df1['a'])
>>> df1
          a         b         c         d
6 -0.269221 -0.026476  0.997517  1.294385
8  0.917438  0.847941  0.034235 -0.448948

>>> df1['e'] = pd.Series(np.random.randn(sLength), index=df1.index)
>>> df1
          a         b         c         d         e
6 -0.269221 -0.026476  0.997517  1.294385  1.757167
8  0.917438  0.847941  0.034235 -0.448948  2.228131

>>> pd.version.short_version
'0.16.1'

SettingWithCopyWarning的目的是通知数据帧副本上可能存在的无效赋值。它不一定会说你做错了(它可能会触发假阳性),但从0.13.0开始,它会让你知道有更多适合相同目的的方法。然后,如果您得到警告,只需遵循它的建议:尝试使用.loc[row_index,col_indexer] = value代替

>>> df1.loc[:,'f'] = pd.Series(np.random.randn(sLength), index=df1.index)
>>> df1
          a         b         c         d         e         f
6 -0.269221 -0.026476  0.997517  1.294385  1.757167 -0.050927
8  0.917438  0.847941  0.034235 -0.448948  2.228131  0.006109
>>> 

事实上,这是目前熊猫文档中描述的更有效的方法


最初的回答:

使用原始的df1索引创建系列:

df1['e'] = pd.Series(np.random.randn(sLength), index=df1.index)