pandas dataframe multiplier par une série
Quelle est la meilleure façon de multiplier toutes les colonnes D'un Pandas DataFrame
par un vecteur colonne stockées dans un Series
? J'ai utilisé pour ce faire dans Matlab avec repmat()
, qui n'existe pas dans les Pandas. Je peux utiliser np.tile()
, mais il semble laid pour convertir la structure de données d'avant en arrière à chaque fois.
Merci.
3 réponses
Qu'est-ce qui ne va pas avec
result = dataframe.mul(series, axis=0)
?
http://pandas.pydata.org/pandas-docs/stable/basics.html#flexible-binary-operations
cela peut être accompli tout simplement avec la méthode DataFrame apply
.
In[1]: import pandas as pd; import numpy as np
In[2]: df = pd.DataFrame(np.arange(40.).reshape((8, 5)), columns=list('abcde')); df
Out[2]:
a b c d e
0 0 1 2 3 4
1 5 6 7 8 9
2 10 11 12 13 14
3 15 16 17 18 19
4 20 21 22 23 24
5 25 26 27 28 29
6 30 31 32 33 34
7 35 36 37 38 39
In[3]: ser = pd.Series(np.arange(8) * 10); ser
Out[3]:
0 0
1 10
2 20
3 30
4 40
5 50
6 60
7 70
Maintenant que nous avons notre DataFrame
et Series
nous avons besoin d'une fonction pour passer à apply
.
In[4]: func = lambda x: np.asarray(x) * np.asarray(ser)
Nous pouvons la transmettre à df.apply
et nous êtes bon pour aller
In[5]: df.apply(func)
Out[5]:
a b c d e
0 0 0 0 0 0
1 50 60 70 80 90
2 200 220 240 260 280
3 450 480 510 540 570
4 800 840 880 920 960
5 1250 1300 1350 1400 1450
6 1800 1860 1920 1980 2040
7 2450 2520 2590 2660 2730
df.apply
agit par colonne par défaut, mais il peut aussi agir par ligne en passant axis=1
comme argument pour apply
.
In[6]: ser2 = pd.Series(np.arange(5) *5); ser2
Out[6]:
0 0
1 5
2 10
3 15
4 20
In[7]: func2 = lambda x: np.asarray(x) * np.asarray(ser2)
In[8]: df.apply(func2, axis=1)
Out[8]:
a b c d e
0 0 5 20 45 80
1 0 30 70 120 180
2 0 55 120 195 280
3 0 80 170 270 380
4 0 105 220 345 480
5 0 130 270 420 580
6 0 155 320 495 680
7 0 180 370 570 780
cela pourrait être fait de façon plus concise en définition de la fonction anonyme à l'intérieur de apply
In[9]: df.apply(lambda x: np.asarray(x) * np.asarray(ser))
Out[9]:
a b c d e
0 0 0 0 0 0
1 50 60 70 80 90
2 200 220 240 260 280
3 450 480 510 540 570
4 800 840 880 920 960
5 1250 1300 1350 1400 1450
6 1800 1860 1920 1980 2040
7 2450 2520 2590 2660 2730
In[10]: df.apply(lambda x: np.asarray(x) * np.asarray(ser2), axis=1)
Out[10]:
a b c d e
0 0 5 20 45 80
1 0 30 70 120 180
2 0 55 120 195 280
3 0 80 170 270 380
4 0 105 220 345 480
5 0 130 270 420 580
6 0 155 320 495 680
7 0 180 370 570 780
pourquoi ne pas créer votre propre fonction de tuile de dataframe:
def tile_df(df, n, m):
dfn = df.T
for _ in range(1, m):
dfn = dfn.append(df.T, ignore_index=True)
dfm = dfn.T
for _ in range(1, n):
dfm = dfm.append(dfn.T, ignore_index=True)
return dfm
Exemple:
df = pandas.DataFrame([[1,2],[3,4]])
tile_df(df, 2, 3)
# 0 1 2 3 4 5
# 0 1 2 1 2 1 2
# 1 3 4 3 4 3 4
# 2 1 2 1 2 1 2
# 3 3 4 3 4 3 4
Toutefois, le docs remarque: "DataFrame n'est pas destiné à remplacer le ndarray car sa sémantique d'indexation est très différente par endroits d'une matrice." ce qui devrait probablement être interprété comme "utiliser numpy si vous faites beaucoup de la matrice des trucs".