我需要用每组的平均值来填充pandas数据帧中缺失的值。根据this questiontransform
可以实现这一点。在
但是,transform
对我来说太慢了。在
例如,使用具有100个不同组和70%NaN
值的大型数据帧进行以下设置:
import pandas as pd
import numpy as np
size = 10000000 # DataFrame length
ngroups = 100 # Number of Groups
randgroups = np.random.randint(ngroups, size=size) # Creation of groups
randvals = np.random.rand(size) * randgroups * 2 # Random values with mean like group number
nan_indices = np.random.permutation(range(size)) # NaN indices
nanfrac = 0.7 # Fraction of NaN values
nan_indices = nan_indices[:int(nanfrac*size)] # Take fraction of NaN indices
randvals[nan_indices] = np.NaN # Set NaN values
df = pd.DataFrame({'value': randvals, 'group': randgroups}) # Create data frame
通过使用transform
在我的电脑上已经花了3秒多。我需要一个数量级更快的东西(买一台更大的机器不是一个选择:-D)。在
那么如何更快地填充缺失的值呢?在
这里有一个使用^{} 的NumPy方法,对于这种基于bin的求和/平均操作非常有效-
注意,这将更新
value
列。在运行时测试
数据大小:
^{pr2}$时间安排:
20x+
加速!在使用排序索引+
fillna()
你说得对-你的代码需要3.18秒才能运行。@piRSquared提供的代码需要2.78秒才能运行。在
示例代码:
%%timeit df2 = df1.groupby("group").transform(lambda x: x.fillna(x.mean()))
Output: 1 loop, best of 3: 3.18 s per loop`
piRSquared的改进:
%%timeit df[['value']].fillna(df.groupby('group').transform('mean'))
Output: 1 loop, best of 3: 2.78 s per loop
稍微更有效的方法(使用排序索引和
fillna
):您可以将
group
列设置为dataframe的索引,并对其进行排序。在df = df.set_index('group').sort_index()
现在已经有了排序索引,通过使用
df.loc[x,:]
按组号访问数据帧的子集是非常便宜的因为您需要用每个组的平均值进行插补,所以您需要所有唯一的组id。对于本例,您可以使用
range
(因为组是从0到99),但更一般地说,您可以使用:groups = np.unique(set(df.index))
在这之后,您可以迭代这些组并使用
fillna()
进行插补:%%timeit for x in groups: df.loc[x,'value'] = df.loc[x,'value'].fillna(np.mean(df.loc[x,'value']))
Output: 1 loop, best of 3: 231 ms per loop
注意:}操作是一次性成本。公平地说,在我的机器上,总时间(包括这些操作)是2.26秒,但插补只花了231毫秒
set_index
、sort_index
和{你做错了。它很慢,因为您正在使用
lambda
相关问题 更多 >
编程相关推荐