我有数千个pd.Series
项目,我只想添加它们。他们考虑不同的时间间隔,我需要用零填充缺失的值。我尝试过
add_series = lambda a, b: a.add(b, fill_value=0).fillna(0)
result = reduce(add_series, all_my_items)
这比我预期的要花费更多的时间。有什么方法可以大大加快速度吗?
答案 0 :(得分:2)
使用concat
pd.concat(all_my_items,axis=1).fillna(0).sum(axis=1)
答案 1 :(得分:0)
您可以通过np.pad
和np.vstack
下拉至NumPy。为了提高性能,在操作Pandas / NumPy对象时,应避免使用常规的Python方法。
以下解决方案假定每个系列均按索引对齐,即,每个系列的 k th 项目按位置在每个 k的系列中具有可比性。
np.random.seed(0)
m, n = 10**2, 10**4
S = [pd.Series(np.random.random(np.random.randint(0, m))) for _ in range(n)]
def combiner(arrs):
n = max(map(len, arrs))
L = [np.pad(i.values, (0, n-len(i)), 'constant') for i in arrs]
return np.vstack(L).sum(0)
res1 = pd.concat(L, axis=1).fillna(0).sum(axis=1)
res2 = pd.Series(combiner(S))
assert (res1 == res2).all()
%timeit pd.concat(L, axis=1).fillna(0).sum(axis=1) # 2.63 s per loop
%timeit pd.Series(combiner(S)) # 863 ms per loop
答案 2 :(得分:0)
您可以使用pd.concat
,但可以同时使用axis=0
和groupby
上的level=0
,例如:
pd.concat(all_my_items,axis=0).groupby(level=0).sum()
其中all_my_items
包含1000个pd.Series
,它们的长度不同(例如2000年至2500年之间),并且具有不同的时间间隔,例如:
import numpy as np
np.random.seed(0)
n = 1000 #number of series
#lengths of the series
len_ser = np.random.randint(2000, 2500, n)
# to pick a random start date
list_date = pd.date_range(start = pd.to_datetime('1980-01-01'), periods=15000).tolist()
# generate the list of pd.Series
all_my_items = [pd.Series(range(len_ser[i]),
index=pd.date_range(start=list_date[np.random.randint(0,15000,1)[0]],
periods=len_ser[i]))
for i in range(n)]
# Wen's solution
%timeit pd.concat(all_my_items,axis=1).fillna(0).sum(axis=1) #1.47 s ± 138 ms per loop
#this solution
%timeit pd.concat(all_my_items,axis=0).groupby(level=0).sum() #270 ms ± 11.3 ms
#verify same result
print (pd.concat(all_my_items,axis=1).fillna(0).sum(axis=1) ==
pd.concat(all_my_items,axis=0).groupby(level=0).sum()).all()) #True
所以结果是一样的,而且操作更快