Python 在列表中修改数据帧不起作用
我有两个Python 在列表中修改数据帧不起作用,python,list,pandas,iteration,Python,List,Pandas,Iteration,我有两个数据帧,我想执行相同的清理操作列表。 我意识到我可以合并成一个,一次完成所有的事情,但我仍然好奇为什么这个方法不起作用 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] })
数据帧
,我想执行相同的清理操作列表。
我意识到我可以合并成一个,一次完成所有的事情,但我仍然好奇为什么这个方法不起作用
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的情况下接受RAW:我试过了
for df in [test_1, test_2]:
df = df[pd.notnull(df["A"])]
但是test_2
保持不变。另一方面,如果我这样做:
test_2 = test_2[pd.notnull(test_2["A"])]
现在,第一个原始数据消失了。所有这些切片/索引操作创建原始数据帧的视图/副本,然后您将
df
重新分配给这些视图/副本,这意味着根本不接触原始数据帧
选项1dropna(…inplace=True)
尝试一个就地
dropna
调用,这将在原地修改原始对象
df_list = [test_1, test_2]
for df in df_list:
df.dropna(subset=['A'], inplace=True)
注意,这是我为数不多的几次推荐就地修改之一,特别是因为这个用例
选项2
通过重新分配枚举
或者,您可以重新分配到列表-
for i, df in enumerate(df_list):
df_list[i] = df.dropna(subset=['A']) # df_list[i] = df[df.A.notnull()]
您正在修改数据帧的副本,而不是原始数据帧
解决这个问题的一种方法是使用字典。为了方便起见,您可以使用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
,我们没有使用pd.concat
触发到int
的转换
[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]
您正在将输出分配给循环变量
df
。底层的数据帧是不变的。相关:我觉得需要一个关于“为什么我的数据帧在x操作后没有改变”的规范问答@pault是的,这是经常被问到的问题之一,但是在如此不起眼的标题下,没有办法在合理的时间内找到它们!我将把这个问题加入书签,并从现在起将其保留在我的目标列表中:)@pault不是专门针对熊猫的,但我认为我们对这个问题有一个规范的答案ᴏʟᴅsᴘᴇᴇᴅ 你说的是查看。我也这么想,var只是底层df
的一个视图,我正在修改它