Quelle est la meilleure façon de multiplier toutes les colonnes d'un Pandas DataFrame
par un vecteur de colonne stocké dans un Series
? J'avais l'habitude de le faire dans Matlab avec repmat()
, qui n'existe pas dans Pandas. Je peux utiliser np.tile()
, mais ça a l'air moche de convertir la structure de données d'avant en arrière à chaque fois.
Merci.
Quel est le problème avec
result = dataframe.mul(series, axis=0)
?
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 nos 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 transmettre ceci à df.apply
et nous sommes prêts à partir
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 également 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 manière plus concise en définissant la fonction anonyme dans 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 mosaïque de trame de données:
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
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
Cependant , la note docs : "DataFrame n'est pas destinée à remplacer directement ndarray comme sa sémantique d'indexation est assez différente à certains endroits d'une matrice. " Ce qui devrait probablement être interprété comme " utilisez numpy si vous faites beaucoup de matrices de matrices ".