将多个空列添加到pandas DataFrame


76

如何将多个空列添加到DataFrame列表中的?

我可以:

    df["B"] = None
    df["C"] = None
    df["D"] = None

但是我不能:

    df[["B", "C", "D"]] = None

KeyError: "['B' 'C' 'D'] not in index"


None不同于0,但是一些答案假设它是等效的。同样,分配None将给出对象的dtype,但是分配0将给出int的dtype。
smci

你也可以这样做df[['B','C','D']] = None, None, None[None, None, None]pd.DataFrame([None, None, None])
SMCI

Answers:


71

concat使用的是DataFrame:

In [23]:
df = pd.DataFrame(columns=['A'])
df

Out[23]:
Empty DataFrame
Columns: [A]
Index: []

In [24]:    
pd.concat([df,pd.DataFrame(columns=list('BCD'))])

Out[24]:
Empty DataFrame
Columns: [A, B, C, D]
Index: []

因此,通过传递包含原始df的列表以及包含您要添加的列的新列表,这将返回包含其他列的新df。


警告:请参阅其他答案和/或评论讨论中有关性能的讨论。reindex在性能至关重要的情况下可能更可取。


谢谢,有可能我遗漏了一些东西,但是我补充说pd.concat([df,pd.DataFrame(columns=list('BCD'))])–它没有任何作用。可能是因为我使用了df = pd.read_csv而不是df = pd.DataFrame
PAN

2
您需要分配concat的结果,例如df=pd.concat([df,pd.DataFrame(columns=list('BCD'))])
EdChum 2015年

1
那不应该发生的,您可以使用花式索引来更改列顺序:df.ix[:, col_list]或者仅通过选择它们并将它们分配回原始df即可:df = df[col_list]
EdChum 2015年

1
这不再起作用了(使用熊猫0.19.1)。串联结果为TypeError: data type not understood
–thenaturalist

1
@thenaturalist抱歉,这在大熊猫中仍然对我有用,0.19.1您需要发布可以运行的完整代码
EdChum

78

您可以df.reindex用来添加新列:

In [18]: df = pd.DataFrame(np.random.randint(10, size=(5,1)), columns=['A'])

In [19]: df
Out[19]: 
   A
0  4
1  7
2  0
3  7
4  6

In [20]: df.reindex(columns=list('ABCD'))
Out[20]: 
   A   B   C   D
0  4 NaN NaN NaN
1  7 NaN NaN NaN
2  0 NaN NaN NaN
3  7 NaN NaN NaN
4  6 NaN NaN NaN

reindex 将返回一个新的DataFrame,其列按列出的顺序显示:

In [31]: df.reindex(columns=list('DCBA'))
Out[31]: 
    D   C   B  A
0 NaN NaN NaN  4
1 NaN NaN NaN  7
2 NaN NaN NaN  0
3 NaN NaN NaN  7
4 NaN NaN NaN  6

reindex方法也作为fill_value参数:

In [22]: df.reindex(columns=list('ABCD'), fill_value=0)
Out[22]: 
   A  B  C  D
0  4  0  0  0
1  7  0  0  0
2  0  0  0  0
3  7  0  0  0
4  6  0  0  0

4
在尝试了一个中等大小的数据帧(约2.5k行,80k列)之后,该解决方案似乎比接受的解决方案快了几个数量级。BTW是有一个原因,为什么该特定命令不接受“ inplace = True”参数?df = df.reindex(...)似乎占用了大量RAM。
Marco Spinaci

5
@MarcoSpinaci:我建议不要使用inplace=True。它没有做大多数人认为的那样。在后台,总是创建一个全新的DataFrame,然后将来自新DataFrame的数据复制到原始DataFrame中。那不会节省任何内存。inplace=True没有实质性的橱窗装饰也是如此,而且,其名称具有误导性。我尚未检查代码,但我预计df = df.reindex(...)至少需要2倍的内存df,并且在reindex用于扩展行数时当然会更多。
unutbu

尽管如此,@ unutbu在迭代容器(例如列表或字典)时非常有用,它可以避免使用使代码更脏的索引...
toto_tico

@unutbu,当我分析了约200个列的创建代码时,确实确实要快得多,您能否简要解释一下为什么进行重新索引比concat快得多,或者只是将多个列设置为一个numpy数组?
山姆

34

如果您不想重写旧列的名称,则可以使用reindex:

df.reindex(columns=[*df.columns.tolist(), 'new_column1', 'new_column2'], fill_value=0)

完整示例

In [1]: df = pd.DataFrame(np.random.randint(10, size=(3,1)), columns=['A'])

In [1]: df
Out[1]: 
   A
0  4
1  7
2  0

In [2]: df.reindex(columns=[*df.columns.tolist(), 'col1', 'col2'], fill_value=0)
Out[2]: 

   A  col1  col2
0  1     0     0
1  2     0     0

并且,如果您已经有了包含列名称的列表,请执行以下操作:

In [3]: my_cols_list=['col1','col2']

In [4]: df.reindex(columns=[*df.columns.tolist(), *my_cols_list], fill_value=0)
Out[4]: 
   A  col1  col2
0  1     0     0
1  2     0     0

2
谢谢。你能告诉我是什么*做的reindex输入吗?
Bowen Liu

2
它将列表解压缩为位置参数,它是Python运算符
toto_tico18年

5

为什么不使用循环:

for newcol in ['B','C','D']:
    df[newcol]=np.nan

0与“无”不同。同样,它将强制dtype为整数,而None则不会。
smci

3

替代解决方案摘要:

columns_add = ['a', 'b', 'c']
  1. for循环:

    for newcol in columns_add:
        df[newcol]= None
    
  2. dict方法:

    df.assign(**dict([(_,None) for _ in columns_add]))
    
  3. 元组分配:

    df['a'], df['b'], df['c'] = None, None, None
    

df.assign(**dict.fromkeys(columns_add, None))应该也可以工作
Joe Ferndz

0

只是添加到有趣的方式列表中:

columns_add = ['a', 'b', 'c']
df = df.assign(**dict(zip(columns_add, [0] * len(columns_add)))

0与“无”不同。同样,它将强制dtype为整数,而None则不会。
smci

无论如何,您都缺少尾随的第四个右括号。
smci

0

我会用

df["B"], df["C"], df["D"] = None, None, None

要么

df["B"], df["C"], df["D"] = ["None" for a in range(3)]
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.