我在 Python pandas 中遇到了一个奇怪的行为。为了防止出现“数据帧高度碎片化”警告,我已经使用了 pd.concat。但之后,当我在连接的数据框中再添加一列时,在某些情况下可能会出现警告。
情况 a:将一个空 df 与多个系列连接起来。然后再添加一列。警告。
情况 b:连接多个系列,然后再添加一列。没关系。
情况 c:连接多个 dfs,然后再添加一列。警告。
import pandas as pd
import sys
print(sys.version) # 3.8.11
print('pandas version: ',pd.__version__) # pandas version: 2.0.3
list_of_series = [pd.Series([1,2,3]) for i in range(200)]
a = pd.DataFrame()
a = pd.concat([a]+list_of_series,axis=1)
a['one_more_col'] = [4,5,6] # concating one df with many series incurs warning
b = pd.concat(list_of_series,axis=1)
b['one_more_col'] = [4,5,6] # concating series only. It's fine.
c = pd.concat([pd.DataFrame(x) for x in list_of_series],axis=1,)
c['one_more_col'] = [4,5,6] # concating many dataframes incurs warning
现在我有两个问题:
顺便说一句,我的问题与这个不同。 性能警告:DataFrame 高度碎片化。这通常是多次调用`frame.insert`的结果,性能较差
在这个问题中,使用 pd.concat 可以防止出现警告。但在我的问题中,我已经使用了 pd.concat,之后再添加一列会在情况 a 和 c 中产生警告。
==========问题已解决==========
@Timus 和@jtobelem。谢谢您的回答。 通过
newframe = df.copy()
复制数据框是有效的。正如警告中提到的那样,df.copy()
似乎神奇地对数据帧进行了碎片整理。我假设 df.assign()
在某处调用 df.copy()
并且它也能工作。
现在仍然很奇怪为什么情况c会引发“碎片数据帧”问题。但
df.copy()
和df.assing()
足以解决它。
在情况 a 中,您将数据框与系列列表连接起来。它将保留对可以修改的数据框 a 的引用:
a = pd.DataFrame()
new_a = pd.concat([a]+list_of_series,axis=1)
那么 a 和 new_a 共享相同的数据,你应该避免这种情况。
考虑使用分配来添加新列:
a = pd.concat(list_of_series,axis=1)
a = a.assign(one_more_col= pd.Series([4,5,6]))
它也适用于情况 b 和 c。