2 votes

Utiliser la fonction Map avec des sous-ensembles d'une série ou d'un dataframe pandas

Disons que j'ai un Dataframe pandas.qui ressemble à ceci :

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

et je cherche à mettre en correspondance une fonction ( DataFrame.corr ) mais je voudrais qu'il prenne n rangs à la fois. Le résultat devrait être une série avec les valeurs de corrélation qui serait plus courte que le DataFrame original ou avec quelques valeurs qui n'ont pas obtenu une pleine n rangs de données.

Existe-t-il un moyen de le faire et comment ? J'ai parcouru la documentation sur DataFrame et Map, Apply, Filter mais il ne semble pas y avoir de solution évidente ou propre.

3voto

piRSquared Points 159

Avec pandas 0.20, en utilisant rolling avec corr produit un cadre de données multi-indexé. Vous pouvez ensuite le découper pour obtenir ce que vous recherchez.

Considérons le cadre de données 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

rolling + 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 ou avant
Avant la version 0.20, rolling + corr a produit un 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
Cependant, je n'étais pas satisfait des réponses ci-dessus. Voici une fonction spécialisée qui prend un nx2 et renvoie une série de corrélations glissantes. CLAUSE DE NON-RESPONSABILITÉ Cette fonction utilise des techniques avancées et ne doit être utilisée que si vous savez ce qu'elle fait. Autrement dit, si vous avez besoin d'une explication détaillée de son fonctionnement... alors ce n'est probablement pas pour vous.

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

Timing
petites données

%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

données importantes

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X