Skip to main content
 首页 » 编程设计

python之将 Map 函数与 pandas 系列或数据框的子集一起使用

2024年08月20日36lyhabc

假设我有一个如下所示的 pandas.Dataframe:

c1 | c2 
------- 
 1 | 5  
 2 | 6  
 3 | 7  
 4 | 8 
 ..... 
 1 | 7 

我正在寻找映射函数 (DataFrame.corr),但我希望它一次获取 n 行。结果应该是一个序列,其相关值比原始 DataFrame 短,或者有一些值没有获得完整的 n 行数据。

有没有办法做到这一点以及如何做到这一点?我一直在查看 DataFrame 和 Map、Apply、Filter 文档,但它似乎没有明显或干净的解决方案。

请您参考如下方法:

在 pandas 0.20 中,使用 rolling 和 corr 会产生一个多索引数据帧。之后您可以切片以找到您要查找的内容。

考虑数据框 df

np.random.seed([3,1415]) 
df = pd.DataFrame(np.random.randint(10, size=(10, 2)), columns=['c1', 'c2']) 
 
   c1  c2 
0   0   2 
1   7   3 
2   8   7 
3   0   6 
4   8   6 
5   0   2 
6   0   4 
7   9   7 
8   3   2 
9   4   3 

滚动 + corr... pandas 0.20.x

df.rolling(5).corr().dropna().c1.xs('c2', level=1) 
# Or equivalently 
# df.rolling(5).corr().stack().xs(['c1', 'c2'], level=[1, 2]) 
 
4    0.399056 
5    0.399056 
6    0.684653 
7    0.696074 
8    0.841136 
9    0.762187 
Name: c1, dtype: float64 

rolling + corr... pandas 0.19.x 或之前版本
在 0.20 之前,rolling + corr 产生了一个 pd.Panel

df.rolling(5).corr().loc[:, 'c1', 'c2'].dropna() 
 
4    0.399056 
5    0.399056 
6    0.684653 
7    0.696074 
8    0.841136 
9    0.762187 
Name: c2, dtype: float64 

numpy + as_strided
但是,我对上述答案并不满意。下面是一个专门的函数,它采用 nx2 数据帧并返回一系列滚动相关性。 免责声明 这使用了一些高级技术,只有当您知道它的作用时才应该真正使用它。这意味着如果您需要详细了解其工作原理……那么它可能不适合您。

from numpy.lib.stride_tricks import as_strided as strided 
 
def rolling_correlation(a, w): 
    n, m = a.shape[0], 2 
    s1, s2 = a.strides 
    b = strided(a, (m, w, n - w + 1), (s2, s1, s1)) 
    b_mb = b - b.mean(1, keepdims=True) 
    b_ss = (b_mb ** 2).sum(1) ** .5 
    return (b_mb[0] * b_mb[1]).sum(0) / (b_ss[0] * b_ss[1]) 
 
def rolling_correlation_df(df, w): 
    a = df.values 
    return pd.Series(rolling_correlation(a, w), df.index[w-1:]) 
 
rolling_correlation_df(df, 5) 
 
4    0.399056 
5    0.399056 
6    0.684653 
7    0.696074 
8    0.841136 
9    0.762187 
dtype: float64 

时机
小数据

%timeit rolling_correlation_df(df, 5) 
10000 loops, best of 3: 79.9 µs per loop 
 
%timeit df.rolling(5).corr().stack().xs(['c1', 'c2'], level=[1, 2]) 
100 loops, best of 3: 14.6 ms per loop 

大数据

np.random.seed([3,1415]) 
df = pd.DataFrame(np.random.randint(10, size=(10000, 2)), columns=['c1', 'c2']) 
 
%timeit rolling_correlation_df(df, 5) 
1000 loops, best of 3: 615 µs per loop 
 
%timeit df.rolling(5).corr().stack().xs(['c1', 'c2'], level=[1, 2]) 
1 loop, best of 3: 1.98 s per loop