Dataframe işlemi

Merhaba,

Ortalama maliyet bulmaya çalıştığım bir csv dosyam var. Aşağıdaki örnek bir ürün için csv nin kısılatılmış hali bunun gibi bir çok ürün var csv dosyasında.

id	tarih	    eylem	urun	kod	birim	miktar	birim fiyat	masraf	toplam
24	7/27/2022	ALIS	makarna	mrk	TL	      12	4.75	    0.12	57.12
37	8/5/2022	ALIS	makarna	mrk	TL	      12	5.07	    0.13	60.97
38	8/9/2022	SATIS	makarna	mrk	TL	      12	5.25	    0.13	62.87
39	8/9/2022	SATIS	makarna	mrk	TL	      12	5.25	    0.13	62.87
83	9/13/2022	ALIS	makarna	mrk	TL	      22	10  	    0.46	220.46
89	9/16/2022	ALIS	makarna	mrk	TL	       5	7.2	        0.08	36.08
115	10/6/2022	ALIS	makarna	mrk	TL	       5	8.13	    0.09	40.74

urun = df_islemler['kod']=="mrk"
eylem1 = df_islemler['eylem']=="ALIS"
eylem2 = df_islemler['eylem']=="SATIS"  

urun_miktari = ((df_islemler.loc[urun&eylem1, 'miktar']).sum())-((df_islemler.loc[urun&eylem2, 'miktar']).sum())
        if urun_miktari == 0:
            print("Stokta Ürün Yok")
        else:
            deger=urun_miktari*(guncel_liste(mrk))
            print(deger)

Yukarıdaki şekilde yaptığımda (yani tüm ALIS ları topla, tüm SATIS ları topla ve bunların farkını al dediğimde) elimde kaç adet ürün olduğunu görebiliyorum. Sonrasında güncel_liste fonksiyonundan ürünün fiyatını alıp elimdeki stokla çarparak stok değerimi bulabiliyorum.

Asıl sorun buradan sonra başlıyor.

Bu liste özelinde bakacak olursak ilk 4 satırda 24 tane alınmış ve 24 tane satılmış. Ondan sonra elde 32 tane daha ürün alınmış. Bu 32 ürünün ortalama maliyeti 9.29 (toplam/32) ama bunu formülüze edemedim.

Fikri olan :slight_smile:

Merhaba,
Yazdığım kodu Kabaca açıklayayım;

eylem” sütununda kaç adet "ALIM" ve kaç adet “SATIS” verisi olduğuğu hesaplatıp aradaki farkı aldım.
Böylece alınmış ancak satılmamış veri sayısını belirledim (3 adet).

Kayıtlar aşağı doğru yenilenerek gittiği için, satılmayan ürünlerin (güncel, en yeni) fiyatlarını bulmak için tail() fonksiyonunu kullanarak sondan (yeni tarihli) 3 adet “ALIM” verisinin toplamlarını sum() fonksiyonu ile hesaplattım.
Aynı şekilde son 3 ALIM verisinin miktarlarını da topladım.

Değerleri birbirine bölerek ortalama birim fiyatı tespit ettim.

import pandas as pd
df = pd.read_excel("liste.ods")
df.head()
id tarih eylem urun kod birim miktar birim fiyat masraf toplam
0 24 2022-07-27 ALIS makarna mrk TL 12 4.75 0.12 57.12
1 37 2022-08-05 ALIS makarna mrk TL 12 5.07 0.13 60.97
2 38 2022-08-09 SATIS makarna mrk TL 12 5.25 0.13 63.13
3 39 2022-08-09 SATIS makarna mrk TL 12 5.25 0.13 63.13
4 83 2022-09-13 ALIS makarna mrk TL 22 10.00 0.46 220.46
alis = df["eylem"] == "ALIS"
sum(alis)
5
satis = df["eylem"] == "SATIS"
sum(satis)
2
satilmayan = sum(alis) - sum(satis)
satilmayan
3
satilmayanlar = df[df["eylem"] == "ALIS"].tail(satilmayan)
satilmayanlar
id tarih eylem urun kod birim miktar birim fiyat masraf toplam
4 83 2022-09-13 ALIS makarna mrk TL 22 10.00 0.46 220.46
5 89 2022-09-16 ALIS makarna mrk TL 5 7.20 0.08 36.08
6 115 2022-10-06 ALIS makarna mrk TL 5 8.13 0.09 40.74
birim_fiyat = satilmayanlar["toplam"].sum() / satilmayanlar["miktar"].sum()
birim_fiyat
9.290000000000001

Yukarıdaki gibi adım adım ilerlemeden, direkt kodu çalıştırıp değeri tespit etmek isterseniz, aşağıdaki kodları kullanabilirsiniz;

alis = sum(df["eylem"] == "ALIS")
satis = sum(df["eylem"] == "SATIS")
satilmayan = alis - satis
satilmayanlar = df[df["eylem"] == "ALIS"].tail(satilmayan)
birim_fiyat = satilmayanlar["toplam"].sum() / satilmayanlar["miktar"].sum()
print(birim_fiyat)

ÇIKTI;

9.290000000000001

Destek için teşekkür ederim. Umarım sonuca ulaşabiliriz.

Eğer ideal bir sistem olsa (alındığı kadar satılsa) bu kod ok ama gerçek dünyaya döndüğümüzde alış ve satış bu kadar simetrik değil. Bunun altına bir satır daha eklediğimizde bu çalışmıyor.

id	tarih   	eylem	urun	kod 	birim	miktar	birim fiyat	masraf	toplam
24	7/27/2022	ALIS	makarna	mrk	TL	12  	4.75	0.12	57.12
37	8/5/2022	ALIS	makarna	mrk	TL	12  	5.07	0.13	60.97
38	8/9/2022	SATIS	makarna	mrk	TL	12  	5.25	0.13	63.13
39	8/9/2022	SATIS	makarna	mrk	TL	12  	5.25	0.13	63.13
83	9/13/2022	ALIS	makarna	mrk	TL 	22  	10  	0.46	220.46
89	9/16/2022	ALIS	makarna	mrk	TL	5   	7.2   	0.08	36.08
115	10/6/2022	ALIS	makarna	mrk	TL	5   	8.13	0.09	40.74
116	10/17/2022	SATIS	makarna	mrk	TL	3   	9   	0.9 	26.1

En alta bir satır ekledim (3 adetlik bir satış geldiğini varsayalım)

Bu sefer ortalama maliyetim 9.22 olması lazım
(32-3 (ilk olarak en eskiden satılır, 22 ürün 19’a düşer) 29 ürün kalır ve 267.28/29 = 9.22)

Bugün biraz daha düşündüm ama nasıl bir yöntem izlemek gerektiğini hala bulamadım :slight_smile:

Sanıyorum ilk bakışta karışık görünen bir cevap olacak.
Kodları satır satır çalıştırırsan mantığı çözersin.

Daha geniş vakitte, temiz kod yazmaya çalışacağım.
Gece gece bu kadar kodlayabildim :slight_smile:


grup = df.groupby("eylem").sum()
alinan = grup.loc["ALIS", "miktar"]
satilan = grup.loc["SATIS", "miktar"]
stok = alinan - satilan

alim_listesi = df[df["eylem"] == "ALIS"]
alim_list = alim_listesi.sort_values(by="tarih", ascending=False)
indis = alim_list.index

sayac = 0
miktar = 0
tutar = 0

for i in range(len(indis)):
    sayac += alim_list.iloc[i,6]
    if sayac <= stok:        
        tutar += alim_list.iloc[i,9]
        miktar += alim_list.iloc[i,6]

    elif sayac > stok:
        son = stok - sayac
        sayac += son
        tutar += (((sayac - miktar) * alim_list.iloc[i,7]) + alim_list.iloc[i,8])
        break

print("Ort. Birim Fiyat:", tutar / sayac)

Aşama aşama kod çıktısı;

import pandas as pd
df = pd.read_excel("liste.ods")
df.head(10)
id tarih eylem urun kod birim miktar birim fiyat masraf toplam
0 24 2022-07-27 ALIS makarna mrk TL 12 4.75 0.12 57.12
1 37 2022-08-05 ALIS makarna mrk TL 12 5.07 0.13 60.97
2 38 2022-08-09 SATIS makarna mrk TL 12 5.25 0.13 63.13
3 39 2022-08-09 SATIS makarna mrk TL 12 5.25 0.13 63.13
4 83 2022-09-13 ALIS makarna mrk TL 22 10.00 0.46 220.46
5 89 2022-09-16 ALIS makarna mrk TL 5 7.20 0.08 36.08
6 115 2022-10-06 ALIS makarna mrk TL 5 8.13 0.09 40.74
7 116 2022-10-17 SATIS makarna mrk TL 3 9.00 0.90 27.90

Gruplama yerine pivot_table() metodu / fonksiyonu da kullanılabilir. Aynı mantık, sonuçta ALIS ve SATIS miktarlarının toplamını tespit etmeye çalışıyoruz.

pivot = pd.pivot_table(data=df, index="eylem", aggfunc='sum') 
pivot
birim fiyat id masraf miktar toplam
eylem
ALIS 35.15 348 0.88 56 415.37
SATIS 19.50 193 1.16 27 152.36

Yukarıdaki kodu pivot_table() metodunun kullanımını görmek için yazdıım, kodun devamında bunu kullanmayacağım. groupby() metodu ile devam edeceğim.

grup = df.groupby("eylem").sum()
grup
id miktar birim fiyat masraf toplam
eylem
ALIS 348 56 35.15 0.88 415.37
SATIS 193 27 19.50 1.16 152.36
alinan = grup.loc["ALIS", "miktar"]
alinan
56
satilan = grup.loc["SATIS", "miktar"]
satilan
27
stok = alinan - satilan
stok
29
alim_listesi = df[df["eylem"] == "ALIS"]
alim_list = alim_listesi.sort_values(by="tarih", ascending=False)
alim_list
id tarih eylem urun kod birim miktar birim fiyat masraf toplam
6 115 2022-10-06 ALIS makarna mrk TL 5 8.13 0.09 40.74
5 89 2022-09-16 ALIS makarna mrk TL 5 7.20 0.08 36.08
4 83 2022-09-13 ALIS makarna mrk TL 22 10.00 0.46 220.46
1 37 2022-08-05 ALIS makarna mrk TL 12 5.07 0.13 60.97
0 24 2022-07-27 ALIS makarna mrk TL 12 4.75 0.12 57.12
indis = alim_list.index
indis
Int64Index([6, 5, 4, 1, 0], dtype='int64')
sayac = 0
miktar = 0
tutar = 0

for i in range(len(indis)):
    sayac += alim_list.iloc[i,6]
    # print("sayac:", sayac)
    if sayac <= stok:        
        tutar += alim_list.iloc[i,9]
        miktar += alim_list.iloc[i,6]
        # print("tutar", tutar, "miktar:", miktar)
    elif sayac > stok:
        son = stok - sayac
        sayac += son
        # print("son:", son, "sayac:", sayac)
        tutar += (((sayac - miktar) * alim_list.iloc[i,7]) + alim_list.iloc[i,8])
        # print(alim_list.iloc[i,7])
        break


# print("tutar:", tutar)
print("Ort. Birim Fiyat:", tutar/sayac)
Ort. Birim Fiyat: 9.216551724137931

Bende gece gece bakamamıştım gündüz temiz kafayla çözdüm, benim yaptıklarımın içine adapte ettim ve gayet temiz çalışıyor.

Çok teşekkür ederim

Rica ederim.
Bu tür sorular, Pandas Kütüphanesi konusunda kendimi geliştirmeme yardımcı olduğu için hoşuma gidiyor.