向 pandas DataFrame 添加多个空列
Posted
技术标签:
【中文标题】向 pandas DataFrame 添加多个空列【英文标题】:Add multiple empty columns to pandas DataFrame 【发布时间】:2015-09-04 18:13:45 【问题描述】:如何将多个空列添加到列表中的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。
你也不能这样做df[['B','C','D']] = None, None, None
或[None, None, None]
或pd.DataFrame([None, None, None])
相关:更一般的How to add multiple columns to pandas dataframe in one assignment?
【参考方案1】:
您可以使用Pandas broadcasting:
df = pd.DataFrame('A': [1, 1, 1])
df[['B', 'C']] = 2, 3
# df[['B', 'C']] = [2, 3]
结果:
A B C
0 1 2 3
1 1 2 3
2 1 2 3
添加空列:
df[['B', 'C', 'D']] = 3 * [np.nan]
结果:
A B C D
0 1 NaN NaN NaN
1 1 NaN NaN NaN
2 1 NaN NaN NaN
【讨论】:
【参考方案2】:替代解决方案总结:
columns_add = ['a', 'b', 'c']
for循环:
for newcol in columns_add:
df[newcol]= None
dict方法:
df.assign(**dict([(_,None) for _ in columns_add]))
元组赋值:
df['a'], df['b'], df['c'] = None, None, None
【讨论】:
df.assign(**dict.fromkeys(columns_add, None))
也应该可以工作【参考方案3】:
我会用
df["B"], df["C"], df["D"] = None, None, None
或
df["B"], df["C"], df["D"] = ["None" for a in range(3)]
【讨论】:
【参考方案4】:为什么不直接使用循环:
for newcol in ['B','C','D']:
df[newcol]=np.nan
【讨论】:
0 与 None 的值不同。此外,它会强制 dtype 为整数,而 None 不会。【参考方案5】:只是添加到有趣的方式列表中:
columns_add = ['a', 'b', 'c']
df = df.assign(**dict(zip(columns_add, [0] * len(columns_add)))
【讨论】:
0 与 None 的值不同。此外,它会强制 dtype 为整数,而 None 不会。 无论如何你都缺少一个尾随的第四个右括号。【参考方案6】:我会 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。
警告:请参阅其他 answers 和/或评论讨论中的性能讨论。 reindex
在性能至关重要的情况下可能更可取。
【讨论】:
谢谢,我可能遗漏了一些东西,但我添加了pd.concat([df,pd.DataFrame(columns=list('BCD'))])
——它什么也没做。难道是因为我使用df = pd.read_csv
而不是df = pd.DataFrame
?
你需要分配concat的结果所以df=pd.concat([df,pd.DataFrame(columns=list('BCD'))])
这不应该发生,您可以使用花哨的索引来更改列顺序:df.ix[:, col_list]
,或者只需选择它们并将它们分配回原始 df:df = df[col_list]
这不再起作用(使用 pandas 0.19.1)。串联导致TypeError: data type not understood
。
@thenaturalist 抱歉,这仍然适用于我在 pandas 0.19.1
你需要发布我可以运行的完整代码【参考方案7】:
如果你不想重写旧列的名称,那么你可以使用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
【讨论】:
谢谢。您能告诉我*
在reindex
输入中的作用吗?
它将列表解包为位置参数,它是a Python operator
不错的解决方案。顺便说一句,没有必要打电话给tolist()
。【参考方案8】:
您可以使用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
【讨论】:
在尝试了一个中等大小的数据框(约 2.5k 行,80k 列)之后,这个解决方案似乎比接受的解决方案快几个数量级。顺便说一句,这个特定命令是有原因的不接受“inplace=True”参数? df = df.reindex(...) 似乎消耗了相当多的 RAM。 @MarcoSpinaci:我建议不要使用inplace=True
。它不像大多数人认为的那样做。在底层,总是会创建一个全新的 DataFrame,然后将来自新 DataFrame 的数据复制到原始 DataFrame 中。这不会节省任何内存。所以inplace=True
是装点门面,没有实质内容,而且名称有误导性。我没有检查代码,但我预计df = df.reindex(...)
需要至少 2 倍于df
所需的内存,当然当reindex
用于扩展行数时更多。
@unutbu,不过,它在迭代容器时很有用,例如一个列表或字典,它会避免使用使代码更脏的索引......
@unutbu 当我分析我的约 200 列创建代码时,它确实快了很多,您能否简要解释一下为什么做 reindex 比 concat 快得多,或者只是将多个列设置为一个 numpy 数组?跨度>
以上是关于向 pandas DataFrame 添加多个空列的主要内容,如果未能解决你的问题,请参考以下文章
将 pandas Series 或 DataFrame 列插入现有 Excel 文件的第一个空列(使用 OpenPyXL?)
Python Pandas 向DataFrame中添加一行/一列
pandas使用pad函数向dataframe特定数据列的每个字符串添加前置(前缀)补齐字符或者字符串向所有字符串的左侧填充直到宽度达到指定要求(left padding)
当列是现有列的布尔测试时,为啥向 Pandas DataFrame 添加列会返回 SettingWithCopy 警告?