For döngüsü hakkında soru

Selamlar,

içinden çıkamadığım bir sorunum var umarım çözüm üretebiliriz.

      alis_tarihi  alis_fiyati  miktar  guncel  satis_fiyati  \
0   10-06-2022       1.1900   83.00    1.62          1.38   
1   27-06-2022       4.5600   21.00    5.13          5.05   
2   04-07-2022      19.4100    5.00   19.80           NaN   
3   05-07-2022      47.7000    2.00   49.70         50.15   
4   06-07-2022      11.2000   10.00   11.04         11.90   
5   07-07-2022      18.5000    5.00   19.80           NaN   
6   21-07-2022      35.2000    3.00   36.32           NaN   
7   22-07-2022      32.4200    3.00   34.96         35.06   
8   22-07-2022      36.1200    3.00   36.20           NaN   
9   26-07-2022      14.1000    7.00   14.17           NaN   
10  27-07-2022     166.5000    1.00  166.50           NaN   
11  27-07-2022       4.7500   12.00    4.81           NaN   
12  26-07-2022      18.0228    0.91   17.88           NaN   
13  27-07-2022      18.0429    0.20   17.88           NaN   

   satis_tarihi  
0    22-07-2022      
1    25-07-2022      
2           NaN       
3    19-07-2022      
4    19-07-2022      
5           NaN       
6           NaN       
7    27-07-2022      
8           NaN       
9           NaN       
10          NaN       
11          NaN       
12          NaN       
13          NaN       

şeklinde bir dataframe’im var. Buna arada işlem yaptırıp yeni bir sütun eklemek istiyorum.

sf=df['satis_tarihi']
for i in sf:
    if sf is not None:
        yuzde=round((((df['satis_fiyati']/df['alis_fiyati'])*100)-100),2)
    else:
        yuzde=round((((df['guncel']/df['alis_fiyati'])*100)-100),2)
    print(yuzde)

Amacım satis_tarihi sütununda veri varsa yuzde’yi hesaplaması eğer yoksa da başka türlü bir hesaplama yöntemine gitmesi.

0     15.97
1     10.75
2       NaN
3      5.14
4      6.25
5       NaN
6       NaN
7      8.14
8       NaN
9       NaN
10      NaN
11      NaN
12      NaN
13      NaN

döngüden böyle bir sonuç geliyor (ayrıca her nedense 14 kez geliyor (toplam satır sayısı kadar döndürüyor halbuki 1 kez döndürmesi gerekmez mi?))

if ile yaptığı işlem doğru ama neden else 'den NaN veriyor? ve bu durumu nasıl çözebilirim?

Su loop’un amaci nedir?

Loop’a girdigimize gore sf None olamaz.

satis/alis kolonunun NaN olan degerlerini guncel/alis ile degistirmek yetmez mi?

for i in sf nin amacı sf içindeki her elemana işlem yaptırıp bir listeye almak sonra bi listeyi yeni bir sütun olarak df içine eklemek.

NaN degerlerin kontrolunu bu sekilde degil de,

if pd.isnull(sf):

ile saglamak daha dogru degil mi?

>>> np.nan == None
False

Dataframe’deki NaN ile Python’da bir veri tipi olan None ayni seyi ifade etmiyor sanirim.

sf=df['satis_tarihi']
for i in sf:
    if pd.isnull(sf):
        yuzde=round(((([df['satis_fiyati']/df['alis_fiyati'])*100)-100),2)
    else:
        yuzde=round(((([df['guncel']/df['alis_fiyati'])*100)-100),2)
  
df.insert(6, 'kar', yuzde)

if pd.isnull(sf): kullanınca

raise ValueError(
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

şeklinde bir hata verdi.

Geçici bir sütun oluşturup satiş fiyatını, satış fiyatı olmaması durumunda güncel fiyatı buraya aktarıp, tek bir formül ile oran hesabı yapalım.

oranlar belirlendikten sonra, oran adında sütun oluşturup değerleri oraya atayalım.

Son olarak ta geçici olarak oluşturduğumuz sütunu silelim.

import pandas as pd
df = pd.read_excel("bfiyat.xlsx")
df

Orijinal Veri Çerçevemiz (DataFrame);

alis_tarihi alis_fiyati miktar guncel satis_fiyati satis_tarihi
0 2022-06-10 1.1900 83.00 1.62 1.38 2022-07-22
1 2022-06-27 4.5600 21.00 5.13 5.05 2022-07-25
2 2022-07-04 19.4100 5.00 19.80 NaN NaT
3 2022-07-05 47.7000 2.00 49.70 50.15 2022-07-19
4 2022-07-06 11.2000 10.00 11.04 11.90 2022-07-19
5 2022-07-07 18.5000 5.00 19.80 NaN NaT
6 2022-07-21 35.2000 3.00 36.32 NaN NaT
7 2022-07-22 32.4200 3.00 34.96 35.06 2022-07-27
8 2022-07-22 36.1200 3.00 36.20 NaN NaT
9 2022-07-26 14.1000 7.00 14.17 NaN NaT
10 2022-07-27 166.5000 1.00 166.50 NaN NaT
11 2022-07-27 4.7500 12.00 4.81 NaN NaT
12 2022-07-26 18.0228 0.91 17.88 NaN NaT
13 2022-07-27 18.0429 0.20 17.88 NaN NaT

Yukarıda anlatılan işlemlere ait Kodlar;

df["gecici_satis_fiyati"] = df.satis_fiyati
df.gecici_satis_fiyati = df.satis_fiyati.fillna(value=df.guncel)
df["oran"] = round((((df.satis_fiyati_gecici / df.alis_fiyati ) * 100 ) - 100), 2 )
df.drop("gecici_satis_fiyati", axis=1, inplace=True)
df

Sonuç olarak elde ettiğimiz Veri Çerçevemiz (DataFrame);

alis_tarihi alis_fiyati miktar guncel satis_fiyati satis_tarihi oran
0 2022-06-10 1.1900 83.00 1.62 1.38 2022-07-22 15.97
1 2022-06-27 4.5600 21.00 5.13 5.05 2022-07-25 10.75
2 2022-07-04 19.4100 5.00 19.80 NaN NaT 2.01
3 2022-07-05 47.7000 2.00 49.70 50.15 2022-07-19 5.14
4 2022-07-06 11.2000 10.00 11.04 11.90 2022-07-19 6.25
5 2022-07-07 18.5000 5.00 19.80 NaN NaT 7.03
6 2022-07-21 35.2000 3.00 36.32 NaN NaT 3.18
7 2022-07-22 32.4200 3.00 34.96 35.06 2022-07-27 8.14
8 2022-07-22 36.1200 3.00 36.20 NaN NaT 0.22
9 2022-07-26 14.1000 7.00 14.17 NaN NaT 0.50
10 2022-07-27 166.5000 1.00 166.50 NaN NaT 0.00
11 2022-07-27 4.7500 12.00 4.81 NaN NaT 1.26
12 2022-07-26 18.0228 0.91 17.88 NaN NaT -0.79
13 2022-07-27 18.0429 0.20 17.88 NaN NaT -0.90

demeliydik. Demedigimiz zaman

0     True
1     True
2    False
3     True

gibi bir cikti uretiyor ve if ifadesi True veya False yanit beklerken bunu gorunce kiziyor. any() veya all() ile bunu kontrol altina aliyoruz.

any(), eger gelen degerlerden biri bile True ise True donduruyor, all() eger gelen degerlerin tamami True ise True donduruyor.


Bu arada, if sf is not None: burada degilse kontrolu yapiyoruz o yuzden bizim ifadeyi de if not pd.isnull(sf).all(): diye guncellememiz lazim.

Bu iş ilginç bir hal almaya başladı :slight_smile:

şimdi dediğin gibi all() kullanmak mantıklı gibi geliyor.

sf=df['satis_tarihi']
for i in sf:
    if pd.notnull(sf).all():
        yuzde=round((((df['satis_fiyati']/df['alis_fiyati'])*100)-100),2)
    else:
        yuzde=round((((df['guncel']/df['alis_fiyati'])*100)-100),2)
    print(yuzde)
  
df.insert(6, 'kar', yuzde)

şeklinde yani eğer sf boş değilse ilk işlemi yap (satis/alis) değilse (guncel/alis)
sf boş da olsa dolu da olsa ikinci işlemi yapıyor. halbuki “var-var-yok-var-var-yok-yok” şeklinde devam ediyor.
denemek için if pd.notnull(sf).all(): kullandığımda bu kez if’in ilk satırındaki işlemi doğru yapıyor. diğerlerini nan veriyor.

0     15.97
1     10.75
2       NaN
3      5.14
4      6.25
5       NaN
6       NaN
7      8.14
8       NaN
9       NaN
10      NaN
11      NaN
12      NaN
13      NaN

Yani aslında basit birşey yapmaya çalıştığımı düşünüyorum nasıl bu kadar komplike bişey oldu anlamadım. Bir df var eger satis_tarihi sütünu boşsa (guncel/alis) değilse (satis/alis) işlemini yap ve bundan kar adında yeni bi sütun oluştur :slight_smile: bu kadar zor olmamalıydı

Ben de pek çok yol denedim.
dataframe’deki , NaN ya da NaT değerlerini bir türlü Treu ya da False gibi gördürüp işlem yaptıramadım.

Denediğim işlemler ve aldığım sonuçlar aşağıdadır.

df["satis_tarihi"].info()

Çıktı;

<class 'pandas.core.series.Series'>
RangeIndex: 14 entries, 0 to 13
Series name: satis_tarihi
Non-Null Count  Dtype         
--------------  -----         
5 non-null      datetime64[ns]
dtypes: datetime64[ns](1)
memory usage: 240.0 bytes

Gördüğünüz gibi, datetime tipinde veri yapısı var.

df["satis_tarihi"].info

Çıktı;

<bound method Series.info of 0    2022-07-22
1    2022-07-25
2           NaT
3    2022-07-19
4    2022-07-19
5           NaT
6           NaT
7    2022-07-27
8           NaT
9           NaT
10          NaT
11          NaT
12          NaT
13          NaT
Name: satis_tarihi, dtype: datetime64[ns]>
x = list(df["satis_tarihi"])
x

Çıktı;

[Timestamp('2022-07-22 00:00:00'),
 Timestamp('2022-07-25 00:00:00'),
 NaT,
 Timestamp('2022-07-19 00:00:00'),
 Timestamp('2022-07-19 00:00:00'),
 NaT,
 NaT,
 Timestamp('2022-07-27 00:00:00'),
 NaT,
 NaT,
 NaT,
 NaT,
 NaT,
 NaT]
for i in x:
    print(type(i))

Çıktı;

<class 'pandas._libs.tslibs.timestamps.Timestamp'>
<class 'pandas._libs.tslibs.timestamps.Timestamp'>
<class 'pandas._libs.tslibs.nattype.NaTType'>
<class 'pandas._libs.tslibs.timestamps.Timestamp'>
<class 'pandas._libs.tslibs.timestamps.Timestamp'>
<class 'pandas._libs.tslibs.nattype.NaTType'>
<class 'pandas._libs.tslibs.nattype.NaTType'>
<class 'pandas._libs.tslibs.timestamps.Timestamp'>
<class 'pandas._libs.tslibs.nattype.NaTType'>
<class 'pandas._libs.tslibs.nattype.NaTType'>
<class 'pandas._libs.tslibs.nattype.NaTType'>
<class 'pandas._libs.tslibs.nattype.NaTType'>
<class 'pandas._libs.tslibs.nattype.NaTType'>
<class 'pandas._libs.tslibs.nattype.NaTType'>

Boş boş uğraşma diyorsun if le else le :slight_smile:

Soyle:

  1. Elimizde calistirilabilir bir kod olmadigi icin kendimiz deneyemiyoruz. Denesek bile,
  2. Nasil bir cikti istedigini bilmiyoruz.

Tam olarak yapilmasi istenen seyi (satis varsa satis/alis, satis yoksa guncel/alis) cozum olarak isaretlenen cevaba kadar bilmedik. Eger oyleyse, su dedigim de asagi yukari esdeger:


Bu arada cozumde satis’in NaN’larini guncel’le dolduruyoruz. Benim soyledigim de satis/alis’in NaN’larini guncel/alis ile oldurmakti. Duzgun ifade edemedim, benim hatam.

estağfurullah, öyle birşey demiyorum.

for döngüsü kurarak çözüme ulaşmak, yaptığın şekilde kodlamayı gerektiriyordu, ben de aynı yolu izlerdim ancak Data Frame’de NaN ve NaT değerlerini bir türlü döngü koşullarına uyduramadığım için farklı bir çözüm yöntemi denedim.