- Python Pandas Dersleri
- 1. Pandas Nedir?
- 2. Pandas Kütüphanesini Yükleme ve Çağırma
- 3. Veri Setini Tanıma, Veri Setinin İçeri Aktarılması ve İncelenmesi
- 4. Pandas Series ve Pandas DataFrame Kavramları
- 5. İndeksler
- 6. Filtreleme
- 7. Sütun ve Satır Güncelleme
- 8. Sütun ve Satır Ekleme ve Kaldırma
- 9. Sıralama
- 10. Gruplama ve Özetleme
- 10.1. Tekli Sütunun Bir İstatistik Değeri: median()
- 10.2. Çoklu Sütunların Bir İstatistik Değeri: median()
- 10.3. İstatistiksel Özet: describe()
- 10.4. Değerlerin Saydırılması: value_counts()
- 10.5. Değerlerin Yüzdelere Ayrılması: normalize
- 10.6. Gruplayarak Saydırma, Yüzde Alma ve İndeks İnceleme: groupby(), value_counts(), normalize ve loc
- 10.7. Bir Gruba Göre Bir İstatistik: groupby() ve median()
- 10.8. Bir Gruba Göre Birden Fazla İstatistik: groupby(), agg(), median() ve std()
- 10.9. Bir String İçeriğine Göre Bir İstatistik: groupby(), apply(), lambda, str.contains() ve sum()
- 11. Kayıp Veri
- 11.1. NaN Sayısını Öğrenme: isna() ve sum()
- 11.2. NaN ve Temizliği: dropna()
- 11.3. Kayıp Veriyi Anlatan Manuel Girilmiş String İfadeleri NaN Yapma: replace()
- 11.4. NaN Değerleri String Bir İfadeye Çevirme: fillna()
- 11.5. NaN Değerleri Bir Önceki Değere Çevirme: fillna()
- 11.6. NaN Değerleri Bir Sonraki Değere Çevirme: fillna()
- 11.7. NaN Değerleri Bir İstatistik Değerine Çevirme: fillna() ve mean()
- 11.8. NaN Değerlerinin Interpolasyon Tahmini: fillna() ve interpolate()
- 12. Verilerin Dışarı Aktarılması
Pandas, Python programlama dilinin üzerine inşa edilmiş hızlı, güçlü, esnek ve kullanımı kolay bir açık kaynak veri analizi ve manipülasyonu aracıdır.
Pandas'ı yüklemek için, Python paket yöneticisi olan pip'i kullanabiliriz. Komut, aşağıdaki platformlarda çalıştırılabilir:
- Windows: Komut İstemi (Command Prompt, Cmd) veya PowerShell
- Linux: Terminal
- macOS: Terminal
Cmd kullanarak anlatacağım.
pip install pandas
Versiyon bilgisi yine Cmd'den aşağıdaki gibi öğrenilebilir.
python
import pandas as pd
pd.__version__
Bu dersin ilk paylaşımında 1.5.2 versiyonu kullanılıyor olacak.
Pandas başarıyla yüklendikten sonra aşağıdaki ifadeyi ekleyerek kütüphaneyi çağırabiliriz.
import pandas as pdpd kısaltmasını kullanmak yaygın bir uygulamadır ancak kısaltma isteğe bağlı olarak değiştirilebilir.
Ders anlatımında, İş Yatırım'ın Hisse Değerleri ve Oranları bölümünde bulunan Özet isimli tabloyu kullanacağız. Verilere buradan ulaşabilir ve excel olarak indirebilirsiniz. Veriye erişim tarihim 07/07/2023 olduğu için sizin verileriniz ile farklılıklar olabilir. Eğer GitHub hesabımdaki python-pandas-dersleri repo'sunda bulunan data'dan temelozet.xlsx dosyasını indirirseniz herhangi bir farklılık olmayacaktır.
Veriyi aşağıdaki gibi içeri aktarabiliriz.
import pandas as pd
df = pd.read_excel('./data/temelozet.xlsx')İlerleyen derslerde göreceğimiz DataFrame'in kısaltması olan df'i kullanmak yaygın bir uygulamadır ancak değişken ismi isteğe bağlı olarak değiştirilebilir.
df.head()df.head() ile veri setinin ilk 5 satırına baktık. Burada 5 varsayılan değerdir. Örneğin, df.head(10) ile ilk 10 satıra da bakılabilirdi.
df.tail()df.tail() ile veri setinin son 5 satırına baktık. Burada 5 varsayılan değerdir. Örneğin, df.tail(10) ile son 10 satıra da bakılabilirdi.
Tam olarak satır ve sütun sayısı bilgisini alalım.
df.shapedf.shape veri çerçevesinin boyutunu döndürür ve veri çerçevesinin satır ve sütun sayısını bir demet olarak verir. Örneğimizde, (509, 8) şeklinde bir çıktı veri çerçevesinin 509 satır ve 8 sütundan oluştuğunu gösterir.
(509, 8)
df.info() fonksiyonu veri çerçevesi hakkında daha detaylı bilgiler sunar. Bu fonksiyon, veri çerçevesindeki her sütunun veri tipini, veri tiplerinin sayısal dağılımını, bellek kullanımını, eksik değerleri ve sütunların ve satırların toplamda kaç olduğu bilgisini gösterir.
df.info()df.head() veya df.tail() ile çalıştırdığımızda sütunların eğer sütun sayısı fazla olsaydı sadece bir kısmını görebilirdik. Veri çerçevesindeki sütunların tamamını görmek isteseydik pd.set_option() ile aşağıdaki ayarı yapabilirdik.
pd.set_option('display.max_columns', None)None kullanılmasının amacı, display.max_columns seçeneğini sınırlamadan kaldırmaktır.
Aynı şekilde, satır sayısını da aşağıdaki gibi ayarlayabiliriz.
pd.set_option('display.max_rows', None)None kullanılmasının amacı, display.max_rows seçeneğini sınırlamadan kaldırmaktır.
import pandas as pd
df = pd.read_excel('./data/temelozet.xlsx')Pandas DataFrame (bizim örneğimizde içeri aktardığımız df), iki boyutlu bir veri tablosunu temsil eder ve sütunlar ve satırlar şeklinde düzenlenmiş verileri içerir. Pandas Series ise (bizim örneğimizde içeri aktardığımız df'in herhangi bir sütunu) tek boyutlu bir diziyi temsil eder ve sıralı bir şekilde indekslenmiş verileri içerir.
df_ornek = {
'Kod': ['A1CAP','ACSEL','ADEL','ADESE','AEFES','AFYON','AGESA'],
'Sektör': ['Aracı Kurumlar','Kimyasal Ürün','Kırtasiye','Perakande - Ticaret','Meşrubat / İçecek','Çimento','Sigorta']
}Önce Pandas Series'e çevirelim.
pd_seri = pd.Series(df_ornek['Sektör'], index=df_ornek['Kod'])
pd_seriBu kod satırında, df_ornek sözlüğünden Sektör anahtarına karşılık gelen değerleri alarak bir Pandas Series oluşturduk. pd.Series() işlevini kullanarak df_ornek['Sektör'] listesini ve df_ornek['Kod'] listesini sırasıyla values ve index parametreleri olarak verdik. index, her bir veri noktasını tanımlayan etiketlerden oluşan bir dizidir.
Şimdi Pandas DataFrame'e çevirelim.
pd_df = pd.DataFrame(df_ornek)
pd_dfVeri çerçevesinde 0, 1, 2, ... gibi giden değerler görüyoruz. Bunlar indekstir ve indeksler her bir satırı tanımlayan tekil değerlerdir. Ancak tekil olmak zorunda değillerdir ki ilerleyen derslerde göreceğiz.
Son oluşturduğumuz veri çerçevesinden Sektör sütununa erişmek istediğimizi varsayalım.
pd_df['Sektör']Çıktı tanıdık geliyor. Hemen veri tipine bakalım.
type(pd_df['Sektör'])Çıktının bir seriyi temsil eden pandas.core.series.Series olduğunu göreceğiz. Serilerin tek boyutlu olduğunu öğrenmiştik. Veri çerçeveleri de serilerin birleşmesinden oluşuyor.
Aynı sütuna ulaşmanın bir başka yolu ise nokta notasyonunu kullanmaktır.
pd_df.SektörYine aynı çıktıyı almış olacağız.
Hangi yöntemi tercih etmeliyiz?
pd_df['Sektör'] ifadesi, DataFrame üzerindeki sütuna doğrudan bir dizi indeksi kullanarak erişim sağlar. Bu yöntem, sütun ismi boşluk veya özel karakterler içerdiğinde veya Python programlama dilinde özel bir kelimeyle çakıştığında daha güvenlidir. Örneğin, eğer sütun ismi sutun ismi veya if gibi bir kelime ise bu ifadeleri kullanarak doğrudan sütuna erişim sağlayabiliriz.
pd_df.Sektör ifadesi ise, nokta notasyonunu kullanarak sütuna erişim sağlar. Bu ifade daha kısa ve daha okunabilir bir yazım şekli sunar. Ancak bazı durumlarda, sütun ismi boşluk veya özel karakterler içeriyorsa veya Python programlama dilinde özel bir kelimeyle çakışıyorsa hata verebilir.
Daha önce oluşturduğumuz veri çerçevesine sütunlar ekleyip az önce öğrendiklerimizi pekiştirelim.
df_ornek = {
'Kod': ['A1CAP','ACSEL','ADEL','ADESE','AEFES','AFYON','AGESA'],
'Hisse Adı': ['A1 Capital', 'Acıselsan Acıpayam Selüloz', 'Adel Kalemcilik', 'Adese AVM', 'Anadolu Efes', 'Afyon Çimento', 'Agesa Hayat ve Emeklilik'],
'Sektör': ['Aracı Kurumlar','Kimyasal Ürün','Kırtasiye','Perakande - Ticaret','Meşrubat / İçecek','Çimento','Sigorta'],
'if': [False,False,False,False,True,True,False],
'@nerede': ['İstanbul','Denizli','İstanbul','Konya','İstanbul','İstanbul','İstanbul']
}
pd_df = pd.DataFrame(df_ornek)Hisse Adı sütununa erişmeye çalışalım.
pd_df['Hisse Adı']Bir de nokta notasyonunu kullanalım.
pd_df.Hisse AdıYukarıdaki ifade ile ilgili sütuna erişmeye çalışırsak SyntaxError: invalid syntax hatası alacağız.
Python programlama dilinde anahtar kelime (keyword) olan ve koşullu ifadeleri belirtmek için kullanılan if isimli sütuna erişmeye çalışalım.
pd_df['if']Yukarıdaki ifadeyi kullanırsak ilgili sütuna erişebileceğiz. Bir de nokta notasyonunu kullanalım.
pd_df.ifYukarıdaki ifade ile ilgili sütuna erişmeye çalışırsak SyntaxError: invalid syntax hatası alacağız.
Özel bir karakter olan @'in kullanıldığı sütuna erişmeye çalışalım.
pd_df['@nerede']Yukarıdaki ifadeyi kullanırsak ilgili sütuna erişebileceğiz. Bir de nokta notasyonunu kullanalım.
pd_df.@neredeYukarıdaki ifade ile ilgili sütuna erişmeye çalışırsak SyntaxError: invalid syntax hatası alacağız.
Buraya kadar tek bir sütuna erişimi gördük. Birden fazla sütuna erişmek istediğimizde aşağıdaki ifadeyi kullanıyoruz.
pd_df[['Kod','Hisse Adı']]Yukarıdaki iki duruma dikkat edelim. Birincisi, tek sütuna tek köşeli parantez ([]) ile ulaşırken çoklu sütunlara çift köşeli parantez ([[]]) ile ulaştık. İkincisi, tek sütuna erişirken çıktıyı bir seri olarak alıyorduk ancak çoklu sütunlara erişmek istediğimizde artık bir seri değil bir veri çerçevesi olarak çıktıyı alıyoruz.
Son olarak, sütun isimlerinin tamamını görmek istiyorsak aşağıdaki ifadeyi kullanabiliriz.
pd_df.columnsYukarıdaki ifade ile Index(['Kod', 'Hisse Adı', 'Sektör', 'if', '@nerede'], dtype='object') çıktısını almış olacağız.
Burada iki tane kavram ile tanışacağız: iloc ve loc.
iloc, integer location anlamına gelir ve DataFrame veya Series üzerinde konum tabanlı indeksleme yapmamıza olanak tanır. İndeksler sıfırdan başlar ve satır veya sütunları belirlemek için tamsayı indekslerini kullanır. iloc kullanırken satır veya sütunların konumunu belirtmek için köşeli parantez içinde tamsayı indeksleri kullanırız.
İlk satıra erişelim.
df.iloc[0]Yukarıda indeksin sütun isimleri olduğunu görüyoruz.
Tek bir satıra erişebileceğimiz gibi birden fazla satıra da erişebiliriz. Tıpkı çoklu sütuna erişimde olduğu gibi ilerleyeceğiz.
df.iloc[[0,1]]Görüldüğü üzere çift parantez kullandık ve çıktıyı bir veri çerçevesi olarak aldık.
iloc ile sütunlara da erişebiliriz. Örneğin, ilk iki satırın 5. sütununa erişmeye çalışalım.
df.iloc[[0,1],4]Piyasa Değeri(mn TL) 5. sütun olsa da indeksler sıfırdan başladığı için konumu 4'tür. Ayrıca çıktıyı seri olarak aldık.
Çoklu sütunlara da erişebiliriz. Örneğin, 4. ve 5. sütunlara erişelim.
df.iloc[[0,1],[3,4]]Çoklu olduğu zaman veri çerçevesi olarak alıyoruz.
Son bir bilgi olarak, integer location'ları hangi sırayla yazarsak o sırayla çıktıyı alırız.
df.iloc[[1,0],[4,3]]loc, label location anlamına gelir ve DataFrame veya Series üzerinde etiket tabanlı indeksleme yapmak için kullanılan bir indeksleme yöntemidir.
İlk satıra erişelim. Burada 0 etiketine sahip satırı getireceğiz.
df.loc[0]Tek bir satıra erişebileceğimiz gibi birden fazla satıra da erişebiliriz. Bu defa örnek olarak 0 ve 1 etiketlerine sahip satırları getireceğiz.
df.loc[[0,1]]Buraya kadar yaptıklarımız aslında iloc'ta yaptıklarımıza benziyor ancak biz etiket bazlı ilerliyoruz. Son olarak, son sütuna erişelim.
df.loc[[0,1], 'Sermaye(mn TL)']iloc'tan farklı olarak sütuna erişmek istediğimizde direkt olarak ismini yazdık.
Çoklu sütunlara da erişebiliriz. Örneğin, aşağıdaki iki sütuna erişelim.
df.loc[[0,1], ['Piyasa Değeri(mn TL)','Piyasa Değeri(mn $)']]Yine sütun isimlerini belirttik ve çift parantez kullandık. Aynı zamanda çoklu olduğu için veri çerçevesi olarak aldık.
Son bir bilgi olarak, label location'ları hangi sırayla yazarsak o sırayla çıktıyı alırız.
df.loc[[1,0], ['Piyasa Değeri(mn $)','Piyasa Değeri(mn TL)']]Örneğin, ilk 5 hissenin kod bilgilerine erişmek istediğimizi varsayalım. Bu durumda indeks veya etiketleri tek tek yazmamıza gerek kalmayacak. : kullanarak da ilk 5 satıra erişebiliriz. Burada dikkat etmemiz gereken nokta çift parantez yerine tek parantez kullanacak olmamızdır.
df.iloc[0:4,0]
# veya
df.loc[0:4, 'Kod']Aynısını : kullanarak sütunlar için de yapabiliriz. Kod sütunundan sonra gelen Hisse Adı, Sektör ve Kapanış(TL) sütunlarını da almak istediğimizi varsayalım.
df.iloc[0:4, 0:4]
# veya
df.loc[0:4, 'Kod':'Kapanış(TL)']Sektörlere ve bunlara ait sayılara ulaşalım.
df['Sektör'].value_counts()Görüldüğü üzere, GYO sektörünün sayısı 41 ile ilk sırada yer alıyor. En az şirkete sahip sektörler 1 ile Eğlence Hizmetleri ve Cam olmuş.
Visual Studio Code editörünü kullananlar için: Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings... şeklinde bir bilgilendirme alabilirsiniz. Burada, scrollable element veya text editor seçeneklerine tıklarsanız çıktının tamamını görebilirsiniz.
import pandas as pd
df = pd.read_excel('./data/temelozet.xlsx')dfSol tarafta bir sütunmuş gibi görünen 0, 1, 2, ... değerleri indekstir. İndeksler, bir numaralandırma veya etiketleme mekanizmasıdır. Örneğin, bir liste içindeki elemanların her biri bir indeks değerine sahiptir ve bu indeksler kullanılarak elemanlara erişebiliriz. Örneğimizdeki veri çerçevesinde indeks, satırları etiketlemek veya numaralandırmak için kullanılır. Varsayılan olarak, veri çerçevesinin indeksi sıfırdan başlayan tam sayılarla oluşturulur. Bununla birlikte, indeksler benzersiz olmak zorunda değildir. Yani aynı indeks değeri birden fazla satıra karşılık gelebilir.
İndeks ayarlamayı iki şekilde yapabiliriz. Birincisi, set_index() fonksiyonunu kullanmaktır.
Örneğimizdeki Kod sütununu indeks olarak ayarlamak istediğimizi varsayalım.
df = df.set_index('Kod')
dfYukarıda Kod sütununu indeks olarak ayarladık. Ancak değişiklikleri yine aynı veri çerçevesine atadık. Bunu yapmak yerine inplace parametresini True olarak ayarlayabiliriz.
df.set_index('Kod', inplace=True)
dfİkincisi ise veriyi içeri aktarma sırasında index_col ile indeks ayarlaması yapmaktır.
df = pd.read_excel('./data/temelozet.xlsx', index_col='Kod')
dfİndeksin ne olduğunu aşağıdaki gibi kontrol edebiliriz. name ile indeksin Kod olarak ayarlandığını görebiliriz.
df.indexloc ile THYAO indeksine ulaşalım. Aslında burada iloc ile loc'un ayrımı daha net görmüş olacağız.
df.loc['THYAO']Aynı indeksin Halka AçıklıkOranı (%) değerine bakalım.
df.loc['THYAO', 'Halka AçıklıkOranı (%)']Çıktıyı 50.4 olarak alacağız.
Yeri gelmişken, iloc ile loc'un farkını aşağıdaki gibi gösterebiliriz.
df.iloc[0]Yukarıda iloc A1 Capital indeksinin değerlerini sağlıklı bir şekilde verebilirken loc'u aynı şekilde kullandığımızda KeyError hatası alacağız.
df.loc[0]İndeksi Kod olarak ayarlamıştık. Varsayılan indeks değerlerine aşağıdaki gibi dönebiliriz.
df.reset_index(inplace=True)
dfİndeksleri artan sırada olacak şekilde sıralayabiliriz.
df.sort_index()Eğer sıralamayı azalan sırada yapmak istersek ascending parametresini False yapmamız gerekiyor.
df.sort_index(ascending=False)Eğer sıralamanın kalıcı olmasını istersek inplace parametresini True yapmalıyız.
df.sort_index(ascending=False, inplace=True)
# ya da
df.sort_index(inplace=True)import pandas as pd
df = pd.read_excel('./data/temelozet.xlsx', index_col='Kod')Sektör sütununun Bankacılık olduğu değerleri filtreleyelim.
Filtrelemenin birden fazla yolu olabilir.
İlki olan iç içe yöntemine bakalım.
df[df['Sektör'] == 'Bankacılık']İkinci bir yol olarak loc'u kullanabiliriz. Hatta burada filtrelemenin yanında herhangi bir sütunu da seçebiliriz. Örneğin, Halka AçıklıkOranı (%) sütununu alalım.
df.loc[df['Sektör'] == 'Bankacılık', 'Halka AçıklıkOranı (%)']Birden fazla filtreleme yapmak istediğimizde mantıksal operatörleri kullanabiliriz.
Örneğin, hem Sektör sütunundan Bankacılık değerini hem de Halka AçıklıkOranı (%) sütunundan 50'den büyük olanları alalım ve Hisse Adı sütunundaki değerleri getirelim.
df.loc[(df['Sektör'] == 'Bankacılık') & (df['Halka AçıklıkOranı (%)'] > 50), 'Hisse Adı']Burada, her bir filtreleme işlemini parantez içerisine aldık. Örnekte, ve anlamına gelen & operatörünü kullandık. Bir de veya anlamına gelen | operatörünü kullanalım.
df.loc[(df['Sektör'] == 'Bankacılık') | (df['Halka AçıklıkOranı (%)'] > 50), 'Hisse Adı']Ve anlamına gelen & kullandığımız örneğe uymayan (tersi) değerleri getirelim. Bunun için ~ kullanmamız yeterli olacaktır. Yani, Sektör sütunu Bankacılık dışı olan ve Halka AçıklıkOranı (%) sütunu <=50 olacak ve Hisse Adı değerleri gelecek.
df.loc[~(df['Sektör'] == 'Bankacılık') & ~(df['Halka AçıklıkOranı (%)'] > 50), 'Hisse Adı']Eğer yukarıdaki ifadeyi ~ her iki filtreyi de dışarıdan kapsayacak şekilde yazarsak Sektör sütunu Bankacılık olan ve Halka AçıklıkOranı (%) sütunu >50 olanları ilk başta alıp sonra bunun dışında kalanları alacak ve Hisse Adı değerlerini getirecek. İlk koşula uyan bir tek AKBNK var. Bunun dışında kalan da 508 hisse olacak.
df.loc[~((df['Sektör'] == 'Bankacılık') & (df['Halka AçıklıkOranı (%)'] > 50)), 'Hisse Adı']Alternatif bir yol olarak isin() kullanılabilir.
df_sektor = df.loc[df['Sektör'].isin(['GYO','Bankacılık'])]
df_sektorSadece Hisse Adı sütununu alalım.
df_sektor = df.loc[df['Sektör'].isin(['GYO','Bankacılık']), 'Hisse Adı']
df_sektorYukarıda yapılan işlemin karışık gelmemesi için parçalara ayırabiliriz. Böylece yaptığımız işlem daha net anlaşılabilir.
sektorler = ['GYO','Bankacılık']
sektorler_filtre = df['Sektör'].isin(sektorler)
df_sektor = df.loc[sektorler_filtre, 'Sektör']
df_sektorHisse Adı sadece Enerji içerenleri filtreleyelim. Bunun için bir string'i içerip içermediği kontrolü yapmış olacağız.
df_filtre_enerji = df.loc[df['Hisse Adı'].str.contains('Enerji', na=False)]
df_filtre_enerjiİhtiyacımız olmamasına rağmen na parametresini False olacak şekilde ekledik. İlgili sütunda NA / NaN içerdiğini varsayalım. Bu durumda kodu çalıştırdığımızda ValueError: Cannot mask with non-boolean array containing NA / NaN values hatası alırdık. na=False olarak ayarlandığında, contains() fonksiyonu eksik değerleri içeren satırları dikkate almadan sadece Enerji kelimesini içeren satırları filtrelemek için kullanılır. Yani, Hisse Adı sütununda Enerji kelimesini içeren satırları seçerken eksik değerleri göz ardı eder.
Sadece ilgilendiğimiz Hisse Adı sütununu alalım.
df_filtre_enerji = df.loc[df['Hisse Adı'].str.contains('Enerji', na=False), 'Hisse Adı']
df_filtre_enerjiimport pandas as pd
df = pd.read_excel('./data/temelozet.xlsx', index_col='Kod')Tüm sütunların isimlerini güncelleyelim.
df.columns = [
'HisseAdi',
'Sektor',
'KapanisTL',
'PiyasaDegeriMnTL',
'PiyasaDegeriMnUSD',
'HalkaAciklikOraniYuzde',
'SermayeMnTL'
]
dfTüm sütun isimlerini büyük harfe çevirelim. Bu işlemi tek tek yapmak yerine list comprehension yöntemi ile yapacağız.
df.columns = [sutun.upper() for sutun in df.columns]
dfBu kod, bir Pandas DataFrame'in sütun isimlerini büyük harflere dönüştürmek için kullanılan bir dizi ifadedir. Kod, list comprehension yöntemini kullanarak, DataFrame'in sütunlarını tek tek dolaşarak her bir sütunun ismini büyük harflere dönüştürür ve bu dönüşüm sonucunda oluşan yeni sütun isimlerini DataFrame'in sütunlarına atar.
USD içeren sütunları $ ile değiştirelim.
df.columns = df.columns.str.replace('USD','$')
dfHepsini tekrar list comprehension ile bu defa küçük yapalım.
df.columns = [sutun.lower() for sutun in df.columns]
dfSütun güncellemeyi rename() ile de yapabiliriz. Değişikliklerin uygulanması için inplace parametresini de True yapalım.
df.rename(columns={
'hisseadi':'HisseAdi',
'sektor':'Sektor',
'kapanistl':'KapanisTL',
'piyasadegerimntl':'PiyasaDegeriMnTL',
'piyasadegerimn$':'PiyasaDegeriMnUSD',
'halkaaciklikoraniyuzde':'HalkaAciklikOraniYuzde',
'sermayemntl':'SermayeMnTL'
}, inplace=True)
dfA1CAP etiketine sahip satırdaki bilgileri güncelleyelim.
df.loc['A1CAP'] = ['A1 Capital (Test)','Aracı Kurumlar (Test)',26.80,3618.0,138.7,25.9,135]
dfBurada ilgili satırdaki bazı sütunlara denk gelen değerleri güncelledik. Eğer çok daha fazla sütun olsaydı tek tek hepsini yazmak zor olurdu. Bilgisini değiştirdiğimiz Hisse Adı ve Sektör sütunlarına ait değerleri eski haline getirelim.
df.loc['A1CAP', ['Hisse Adı','Sektör']] = ['A1 Capital','Aracı Kurumlar']
dfEğer tek bir değeri güncellemek istersek bunu iki farklı yoldan yapabiliriz. Birincisi, her zaman kullandığımız loc; ikincisi ise at yöntemi.
df.loc['A1CAP', 'Hisse Adı'] = 'A1 Capital Test'
# veya
df.at['A1CAP', 'Hisse Adı'] = 'A1 Capital Test'
dfBir filtreleme sonrası da tek bir hücre için güncelleme yapılabilir.
df.loc[df['Sektör'] == 'Bankacılık', 'Halka AçıklıkOranı (%)'] = 0
df.loc[df['Sektör'] == 'Bankacılık', 'Halka AçıklıkOranı (%)']Çoklu satır güncellemesi yapmak istediğimiz zaman birkaç farklı yolu kullanabiliriz. Örneğin, Hisse Adı sütunundaki tüm değerleri küçük yapalım. Bunun için birincisi str.lower() kullanabiliriz.
df['Hisse Adı'] = df['Hisse Adı'].str.lower()
dfİkinci bir yol olan apply() ile Hisse Adı sütunundaki tüm değerleri büyük harfli yapalım. Bunun için önce bir fonksiyon yazıp ardından bu fonksiyonu apply() ile uygulayacağız.
def hisse_adi_guncelle(hisse_adi):
return hisse_adi.upper()
df['Hisse Adı'] = df['Hisse Adı'].apply(hisse_adi_guncelle)
dfÜçüncü bir yol olan apply() ve lambda ile Hisse Adı sütunundaki tüm değerlerin yalnızca ilk harflerini büyük bırakalım.
df['Hisse Adı'] = df['Hisse Adı'].apply(lambda x: x.capitalize())
# veya
df['Hisse Adı'] = df['Hisse Adı'].apply(lambda x: x.title())
# veya
df['Hisse Adı'] = df['Hisse Adı'].apply(lambda x: x[0] + x[1:].lower())
dfDördüncü bir yol olan applymap() ve lambda ile Hisse Adı ve Sektör sütunlarındaki harfleri küçük yapalım.
df[['Hisse Adı','Sektör']] = df[['Hisse Adı','Sektör']].applymap(lambda x: x.lower())
dfBeşinci bir yol olan map() veya replace() ile seriler üzerinde güncelleme işlemleri yapabiliriz.
df['Hisse Adı'].map({'a1 capital test':'a1 capital'})Ancak map() yönteminde eşleştirme sözlüğünde yer almayan değerler dönüşüm sırasında NaN olarak kabul edilir. Bu noktada replace() fonksiyonunu kullanabiliriz.
df['Hisse Adı'].replace({'a1 capital test':'a1 capital'})Değişiklikleri kaydetmek için yine aynı veri çerçevesine atayabiliriz.
import pandas as pd
df = pd.read_excel('./data/temelozet.xlsx', index_col='Kod')Hisse Adı sütunu ile Sektör sütununu yeni bir sütunda birleştirelim.
df['HisseAdi@Sektor'] = df['Hisse Adı'] + '@' + df['Sektör']
dfHisse Adı ve Sektör sütunlarına ihtiyacımız olmadığını düşünelim. Bunları drop() yardımıyla kaldırabiliriz. Değişiklikleri de aynı veri çerçevesine inplace parametresini True yapıp kaydedelim.
df.drop(columns=['Hisse Adı','Sektör'], inplace=True)
dfKaldırdığımız sütunları tekrar yerine koyalım. Bunun için str.split() fonksiyonunu kullanacağız.
df['HisseAdi@Sektor'].str.split('@')Sonucu yeni sütunlar olarak genişletelim. Bunu, expand parametresi ile yapacağız.
df['HisseAdi@Sektor'].str.split('@', expand=True)Yeni oluşan sütunları veri çerçevesine ekleyelim.
df[['Hisse Adı','Sektör']] = df['HisseAdi@Sektor'].str.split('@', expand=True)
dfSadece Hisse Adı sütununa bir veri girişi yapalım. Bunu append() ile yapacağız.
df.append({'Hisse Adı':'TEST'})Eğer bu şekilde yaparsak TypeError: Can only append a dict if ignore_index=True hatasını alacağız. Bu hata, yalnızca bir sözlüğü veri çerçevesine ekleyebileceğimizi söylüyor. Bunu ignore_index parametresini True yaparak aşabiliriz.
df.append({'Hisse Adı':'TEST'}, ignore_index=True)Görüldüğü üzere, diğerlerini NaN olarak ekledi.
İki veri çerçevesini birleştirelim. Bunun için bir veri çerçevesi daha oluşturalım. İlk veri çerçevesini de ilk hali ile kullanalım.
df = pd.read_excel('./data/temelozet.xlsx', index_col='Kod')
df2 = {
'Kod':['TST'],
'Hisse Adı':['TEST'],
'Sektör':['Bankacılık'],
'Kapanış(TL)':[0],
'Piyasa Değeri(mn TL)':[0],
'Piyasa Değeri(mn $)':[0],
'Halka AçıklıkOranı (%)':[0],
'Sermaye(mn TL)':[0],
'USDTRY':26
}
df2 = pd.DataFrame(df2)
df2.set_index('Kod', inplace=True)
df2İkinci veri çerçevesinde bir sütun fazla. Bu durumda birleştirme sırasında bunu görmezden geleceğiz.
df3 = df.append(df2, ignore_index=True)
df3Burada aslında çıkan uyarıları da dikkate almamız gerekiyor. Son kodu çalıştırdığımızda bize FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead. şeklinde bir uyarı veriliyor. Bu uyarı, append() fonksiyonunun pandas'ın gelecekteki bir sürümünde kullanımdan kaldırılacağını ve bunun yerine concat() fonksiyonunu kullanmamız gerektiğini söylüyor. Biz de kullanalım.
df3 = pd.concat([df,df2], ignore_index=True)
df3Yine aynı çıktıyı aldık.
509 numaralı indeksi kaldırmak istediğimizi varsayalım. Daha önce kullandığımız drop() fonksiyonunun içine index parametresini ekleyerek kaldırma işlemini gerçekleştirebiliriz.
df3.drop(index=509, inplace=True)
df3Yukarıda sadece bir adet indeks belirtip onu kaldırdık. Sadece Aracı Kurumlar içeren satırları indeks ile kaldırmak istediğimizi varsayalım. Önce koşulu belirteceğiz ardından da bu koşulun indekslerini alacağız.
df3.drop(index=df3[df3['Sektör'] == 'Aracı Kurumlar'].index, inplace=True)
df3import pandas as pd
df = pd.read_excel('./data/temelozet.xlsx', index_col='Kod')Veri çerçevesini kapanış fiyatlarına göre sıralayalım.
df.sort_values(by='Piyasa Değeri(mn $)', inplace=True)
dfYukarıda küçükten büyüğe doğru sıraladık. Şimdi ise büyükten küçüğe doğru sıralayalım.
df.sort_values(by='Piyasa Değeri(mn $)', ascending=False, inplace=True)
dfSektör sütununa göre artan ve Piyasa Değeri(mn $) sütununa göre azalan şekilde sıralayalım.
df.sort_values(by=['Sektör','Piyasa Değeri(mn $)'], ascending=[True, False], inplace=True)
dfİndekse göre artan bir şekilde sıralayabiliriz.
df.sort_index(inplace=True)
dfİndekse göre azalan bir şekilde de sıralayabiliriz.
df.sort_index(ascending=False, inplace=True)
dfSektör sütununu alıp seri olacak şekilde bir sıralama yapabiliriz.
df['Sektör'].sort_values()Piyasa Değeri(mn $) sütununa göre piyasa değeri $ cinsinden en yüksek 10'a bakalım.
df.nlargest(10, 'Piyasa Değeri(mn $)')Piyasa Değeri(mn $) sütununa göre piyasa değeri $ cinsinden en düşük 10'a bakalım.
df.nsmallest(10, 'Piyasa Değeri(mn $)')import pandas as pd
df = pd.read_excel('./data/temelozet.xlsx', index_col='Kod')Piyasa Değeri(mn $) sütununun medyan değerine bakalım.
df['Piyasa Değeri(mn $)'].median()Piyasa değerinin 107.3 milyon $ olduğu öğrendik.
Piyasa Değeri(mn TL) ve Piyasa Değeri(mn $) sütunlarının medyan değerine bakalım.
df[['Piyasa Değeri(mn TL)','Piyasa Değeri(mn $)']].median()Sayısal veri tipine sahip sütunların istatistiksel özetlerine bakalım.
İstatistiksel özet:
- count: Sütundaki non-null (boş olmayan) değerlerin sayısı.
- mean: Sütundaki değerlerin ortalaması.
- std: Sütundaki değerlerin standart sapması.
- min: Sütundaki en küçük değer.
- 25%: Alt çeyrek yüzdesi, sütundaki değerlerin %25'inin altında olan değer.
- 50%: Medyan veya ortanca, sütundaki değerlerin yarısından küçük ve yarısından büyük olan değer.
- 75%: Üst çeyrek yüzdesi, sütundaki değerlerin %75'inin altında olan değer.
- max: Sütundaki en büyük değer.
df_istatistiksel_ozet = df.drop(['Hisse Adı','Sektör'], axis=1)
df_istatistiksel_ozet.describe()axis=0'da (varsayılan değer) işlemler satırlar boyunca yapılır. axis=1'de ise işlemler sütunlar boyunca yapılır.
Sektör sütunundaki değerleri saydıralım.
df['Sektör'].value_counts()Sektör sütunundaki değerleri saydırmıştık. Bunların yüzde paylarını normalize parametresini True yaparak alabiliriz.
df['Sektör'].value_counts(normalize=True)10.6. Gruplayarak Saydırma, Yüzde Alma ve İndeks İnceleme: groupby(), value_counts(), normalize ve loc
Öncelikle Halka AçıklıkOranı (%) sütununa göre yeni bir sütun oluşturalım. 50'den büyüksek >50; küçük veya eşitse <=50 yazsın.
df['HalkaAciklikOraniGrup'] = df['Halka AçıklıkOranı (%)'].apply(lambda x: '>50' if x > 50 else '<=50')
dfŞimdi Sektör sütununa göre HalkaAciklikOraniGrup sütununu saydıralım.
df.groupby(['Sektör'])['HalkaAciklikOraniGrup'].value_counts()İstediğimizi elde ettik. Son olarak örneğin, Teknoloji sektörüne bakalım.
df.groupby(['Sektör'])['HalkaAciklikOraniGrup'].value_counts().loc['Teknoloji']Görüldüğü üzere, ilgilendiğimiz sektördeki halka açıklık dağılımı bilgisine gruplandırılmış olarak ulaştık. Aynı bilgiye yüzde olarak da erişebiliriz.
df.groupby(['Sektör'])['HalkaAciklikOraniGrup'].value_counts(normalize=True).loc['Teknoloji']Sektör sütununa göre sektörlerin piyasa değerlerinin medyanını Piyasa Değeri(mn $) sütununu kullanarak alalım.
df.groupby(['Sektör'])['Piyasa Değeri(mn $)'].median()Sektör sütununa göre sektörlerin piyasa değerlerinin medyanını Piyasa Değeri(mn $) sütununu kullanarak alalım. Bunun yanına bir de standart sapma ekleyelim.
df.groupby(['Sektör'])['Piyasa Değeri(mn $)'].agg(['median','std'])Sütun isimlerini güncelleyebiliriz.
df.groupby(['Sektör'])['Piyasa Değeri(mn $)'].agg(Medyan='median',StandartSapma='std')Hisse Adı sütununda Enerji içeren hisseleri HalkaAciklikOraniGrup sütununa göre saydıralım.
df.groupby(['HalkaAciklikOraniGrup']).apply(lambda x: x['Hisse Adı'].str.contains('Enerji').sum())
# veya
df.groupby(['HalkaAciklikOraniGrup'])['Hisse Adı'].apply(lambda x: x.str.contains('Enerji').sum())import pandas as pd
df = pd.read_excel('./data/temelozet.xlsx', index_col='Kod')Bazı sütunların bazı değerlerini NaN yapalım.
import numpy as np
np.random.seed(34)
random_satirlar = df.sample(n=200)
df2 = df
df2.loc[random_satirlar.index, ['Kapanış(TL)','Piyasa Değeri(mn $)']] = np.nan
df2Her bir sütunda kaç adet NaN olduğunu bulabiliriz.
df2.isna().sum()Eğer yukarıda bir sum() daha eklersek toplam NaN sayısını alırız.
df2.isna().sum().sum()Bu da 400 değerini verecektir.
dropna() kullanarak NaN içeren satırları kaldırabiliriz.
df2.dropna()509 satırlık veri çerçevesinin iki sütununa 200 adet NaN atamıştık. 200'ünü de kaldırıp 309 satırlık bir veri çerçevesi bıraktı.
dropna()'i aşağıdaki gibi özelleştirerek de kullanabilirdik.
df2.dropna(axis='index', how='all', subset=['Kapanış(TL)','Piyasa Değeri(mn $)'])Eksik değerlerin satırlarda bulunduğunu belirtmek için axis='index' parametresi kullanılır. how='all' parametresi, bir satır veya sütunda tüm değerlerin eksik olduğu durumu belirtir. 'all' değeri, tüm değerlerin eksik olduğu satırları çıkarmak için kullanılır. Yani, bir satırdaki tüm belirtilen sütunlarda eksik değer varsa o satır veri çerçevesinden çıkarılır. subset parametresi ile eksik değerlerin kontrol edileceği sütunları belirttik. Sonuç olarak, Kapanış(TL) ve Piyasa Değeri(mn $) sütunlarında eksik değerleri olan satırları veri çerçevesinden çıkardık.
Bazı sütunların bazı değerlerini NaN yapmak yerine Veri Yok yazdığımızı varsayalım.
import numpy as np
np.random.seed(34)
random_satirlar = df.sample(n=200)
df2 = df
df2.loc[random_satirlar.index, ['Kapanış(TL)','Piyasa Değeri(mn $)']] = 'Veri Yok'
df2Veri Yok yazan satırları replace() ile NaN yapalım.
df2.replace(to_replace='Veri Yok', value=np.nan, inplace=True)
df2NaN içeren satırları belirlediğimiz bir string ifadeye çevirelim.
df2.fillna(value='VERI YOK')import numpy as np
np.random.seed(34)
random_satirlar = df.sample(n=200)
df2 = df
df2.loc[random_satirlar.index, ['Kapanış(TL)','Piyasa Değeri(mn $)']] = np.nanBu örnek için pek anlamlı olmasa da nasıl yapıldığını görmek için yapmış olalım. Bunun için method parametresini pad yapacağız.
df2.fillna(method = 'pad')import numpy as np
np.random.seed(34)
random_satirlar = df.sample(n=200)
df2 = df
df2.loc[random_satirlar.index, ['Kapanış(TL)','Piyasa Değeri(mn $)']] = np.nanBu örnek için pek anlamlı olmasa da nasıl yapıldığını görmek için yapmış olalım. Bunun için method parametresini bfill yapacağız.
df2.fillna(method = 'bfill')import numpy as np
np.random.seed(34)
random_satirlar = df.sample(n=200)
df2 = df
df2.loc[random_satirlar.index, ['Kapanış(TL)','Piyasa Değeri(mn $)']] = np.nanBu örnek için pek anlamlı olmasa da nasıl yapıldığını görmek için yapmış olalım. İstatistik olarak ortalamayı kullanalım.
df2.fillna(value=df2['Kapanış(TL)'].mean())import numpy as np
np.random.seed(34)
random_satirlar = df.sample(n=200)
df2 = df
df2.loc[random_satirlar.index, ['Kapanış(TL)','Piyasa Değeri(mn $)']] = np.nanBu örnek için pek anlamlı olmasa da nasıl yapıldığını görmek için yapmış olalım. method parametresini linear yapacağız.
df2.interpolate(method='linear')# En basit haliyle kaydetme
df.to_csv('./data/temelozet_v2.csv')
# İndeksleri çıkarma
df.to_csv('./data/temelozet_v2.csv', index=False)
# Türkçe karakterleri dikkate alma
df.to_csv('./data/temelozet_v2.csv', index=False, encoding='utf-8')
# Zip'li kaydetme
zip_secenekler = dict(method='zip', archive_name='output.csv')
df.to_csv('./data/output.zip', compression=zip_secenekler)
# Farklı bir dosyaya kaydetme (yol-1)
from pathlib import Path
dosya_yolu = Path('./data/data_alt/temelozet_v2.csv')
dosya_yolu.parent.mkdir(parents=True, exist_ok=True)
df.to_csv(dosya_yolu)
# Farklı bir dosyaya kaydetme (yol-2)
import os
os.makedirs('./data/data_alt', exist_ok=True)
df.to_csv('./data/data_alt/temelozet_v2.csv')# En basit haliyle kaydetme
df.to_excel('./data/temelozet_v2.xlsx')
# İndeksleri çıkarma
df.to_excel('./data/temelozet_v2.xlsx', index=False)
# Sheet ismini değiştirme
df.to_excel('./data/temelozet_v2.xlsx', sheet_name='IsYatirim')