我有两个DataFrames
,我想执行相同的清理操作列表。
我意识到我可以合并为一个,并且一次性合并到一切,但我仍然很好奇为什么这个方法不起作用
test_1 = pd.DataFrame({
"A": [1, 8, 5, 6, 0],
"B": [15, 49, 34, 44, 63]
})
test_2 = pd.DataFrame({
"A": [np.nan, 3, 6, 4, 9, 0],
"B": [-100, 100, 200, 300, 400, 500]
})
我们假设我只想在没有NaN
的情况下拍摄原始照片:我试过了
for df in [test_1, test_2]:
df = df[pd.notnull(df["A"])]
但test_2
保持不变。另一方面,如果我这样做:
test_2 = test_2[pd.notnull(test_2["A"])]
现在我第一个原始人就离开了。
答案 0 :(得分:6)
所有这些切片/索引操作都会创建原始数据框的视图/副本,然后重新分配 df
到这些视图/副本,这意味着根本不会触及原件。
选项1
dropna(...inplace=True)
尝试就地dropna
调用,这应该就地修改原始对象
df_list = [test_1, test_2]
for df in df_list:
df.dropna(subset=['A'], inplace=True)
请注意,这是我将推荐就地修改的少数几次之一,特别是因为这个用例。
选项2
enumerate
重新分配
或者,您可以重新分配到列表 -
for i, df in enumerate(df_list):
df_list[i] = df.dropna(subset=['A']) # df_list[i] = df[df.A.notnull()]
答案 1 :(得分:4)
您正在修改数据框的副本而不是原始数据框。
解决此问题的一种方法是使用字典。为方便起见,您可以将pd.DataFrame.pipe
与词典理解结合使用来修改词典。
def remove_nulls(df):
return df[df['A'].notnull()]
dfs = dict(enumerate([test_1, test_2]))
dfs = {k: v.pipe(remove_nulls) for k, v in dfs.items()}
print(dfs)
# {0: A B
# 0 1 15
# 1 8 49
# 2 5 34
# 3 6 44
# 4 0 63,
# 1: A B
# 1 3.0 100
# 2 6.0 200
# 3 4.0 300
# 4 9.0 400
# 5 0.0 500}
注意:在您的结果中dfs[1]['A']
仍为float
:这是因为np.nan
被视为float
而我们尚未触发转化为int
。
答案 2 :(得分:3)
使用pd.concat
[x.reset_index(level=0,drop=True) for _, x in pd.concat([test_1,test_2],keys=[0,1]).dropna().groupby(level=0)]
Out[376]:
[ A B
0 1.0 15
1 8.0 49
2 5.0 34
3 6.0 44
4 0.0 63, A B
1 3.0 100
2 6.0 200
3 4.0 300
4 9.0 400
5 0.0 500]