J'ai un dataframe avec deux colonnes: quantité et prix.

df = pd.DataFrame([
[ 1, 5],
[-1, 6],
[ 2, 3],
[-1, 2],
[-1, 4],
[ 1, 2],
[ 1, 3],
[ 1, 4],
[-2, 5]], columns=['quantity', 'price'])

df['amount'] = df['quantity'] * df['price']
df['cum_qty'] = df['quantity'].cumsum()

J'ai ajouté deux nouvelles colonnes montant et cum_qty (quantité cumulée). Maintenant, le dataframe ressemble à ceci (la quantité positive représente les achats, la quantité négative représente les ventes):

   quantity  price  amount  cum_qty
0         1      5       5        1
1        -1      6      -6        0
2         2      3       6        2
3        -1      2      -2        1
4        -1      4      -4        0
5         1      2       2        1
6         1      3       3        2
7         1      4       4        3
8        -2      5     -10        1

Je voudrais calculer le prix d'achat moyen.

Chaque fois que cum_qty = 0, la quantité et le montant doivent être remis à zéro. Nous regardons donc les lignes avec index = [5,6,7]. Pour chaque ligne, un article est acheté aux prix 2, 3 et 4, ce qui signifie que j'ai en stock 3 chacun au prix moyen de 3 [(2 + 3 + 4) / 3].

Après la vente à l'indice = 8 (les transactions de vente ne changent pas le prix d'achat), j'en aurai une chacune au prix 3.

Donc, fondamentalement, je dois diviser tous les montants d'achat cumulés par les quantités cumulées de la dernière quantité cumulée qui n'est pas zéro.

Comment calculer l'achat en main à la suite de toutes les transactions avec pandas DataFrame?

1
user3225309 2 août 2017 à 01:17

2 réponses

Meilleure réponse

D'après ce que je comprends, vous avez besoin d'un prix d'achat pour chaque cercle commercial, alors vous pouvez essayer ceci.

df['new_index'] = df.cum_qty.eq(0).shift().cumsum().fillna(0.)#give back the group id for each trading circle.*
df=df.loc[df.quantity>0]# kick out the selling action
df.groupby('new_index').apply(lambda x:(x.amount.sum()/x.quantity.sum()))

new_index
0.0    5.0# 1st ave price 5
1.0    3.0# 2nd ave price 3
2.0    3.0# 3nd ave price 3 ps: this circle no end , your position still pos 1
dtype: float64

EDIT1 pour vous exigence supplémentaire

DF=df.groupby('new_index',as_index=False).apply(lambda x : x.amount.cumsum()/ x.cum_qty).reset_index()
DF.columns=['Index','AvePrice']
DF.index=DF.level_1
DF.drop(['level_0',  'level_1'],axis=1,inplace=True)
pd.concat([df,DF],axis=1)

Out[572]: 
         quantity  price  amount  cum_qty  new_index    0
level_1                                                  
0               1      5       5        1        0.0  5.0
2               2      3       6        2        1.0  3.0
5               1      2       2        1        2.0  2.0
6               1      3       3        2        2.0  2.5
7               1      4       4        3        2.0  3.0
1
YOBEN_S 3 août 2017 à 19:56
df[df['cum_qty'].map(lambda x: x == 0)].index

Vous donnera à quelles lignes vous avez un cum_qty de 0

df[df['cum_qty'].map(lambda x: x == 0)].index.max()

Vous donne la dernière ligne avec 0 cum_qty

start = df[df['cum_qty'].map(lambda x: x == 0)].index.max() + 1
end = len(df) - 1

Vous donne les numéros de ligne de début et de fin correspondant à la plage à laquelle vous faites référence

df['price'][start:end].sum() / df['quantity'][start:end].sum()

Vous donne la réponse que vous avez faite dans l'exemple que vous avez donné

Si vous voulez connaître cette valeur pour chaque occurrence de cum_qty 0, vous pouvez appliquer la logique de début / fin en utilisant l'index de chacun (le résultat de ma première ligne de code).

1
Jigl 1 août 2017 à 22:44