我正在寻找关于pandas中非常大的数据帧问题的解决方案。
我们假设我有一个非常大的数据帧,其中包含NA。我想用具有相同ID的行的平均值来填充NA。我知道有些ID与我无关(参见示例代码中的数组" ids")。
我想出了以下代码:
# relevant Ids
ids = [2,3]
# create example dataframe
test = pd.DataFrame([[1,1,4],[1,np.nan,np.nan],[1,3,5],[2,np.nan,3],[2,5,5],[2,7,np.nan],[3,4,np.nan],[3,np.nan,3],[3,8,9]],columns=['id','v1','v2'])
# fill NAs with the mean of the group defined by ID
test[test.id.isin(ids)] = pd.concat([test[test.id.isin(ids)].id,test[test.id.isin(ids)].groupby('id').transform(lambda x: x.fillna(x.mean()))],axis=1)
我在一个循环周围的环境中使用它。 在每个循环中,大约1000行将被添加到数据帧中,我必须为这些行填充NA。
这意味着,我可以从中获得的每一点性能都非常棒。我试图避免创建数据帧的副本,因为这似乎更慢。
也许有人有想法?我认为,例如,应该避免使用isin()三次过滤,但我无法在不复制数据帧的情况下找到解决方案。
我不是python或pandas的专家,所以可能会遗漏一些东西。
答案 0 :(得分:1)
好像你做了很多工作。你不能先替换所有缺失的值,然后过滤
startnode.bat
还有一种没有变换的方法
test[['v1', 'v2']] = test.groupby('id').transform(lambda x: x.fillna(x.mean()))
test[test.id.isin(ids)]
答案 1 :(得分:1)
这是一个循环遍历列的NumPy解决方案 -
a = test.values
ID = a[:,0].astype(int)
for i in range(1,test.shape[1]):
nan_mask = np.isnan(a[:,i])
ids_i = np.intersect1d(ID[~nan_mask], ids) # Account for at least 1 NaN grp
valid_mask = np.in1d(ID, ids_i)
m1 = ~nan_mask & valid_mask
m2 = nan_mask & valid_mask
s1 = np.bincount(ID[m1],a[m1,i])/np.bincount(ID[m1])
test.iloc[m2,i] = s1[ID[m2],None]