Listeler listesi olarak temsil edilen bir tabloyu Pandas DataFrame'e dönüştürmek istiyorum. Son derece basitleştirilmiş bir örnek olarak:
a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]
df = pd.DataFrame(a)
Sütunları uygun türlere, bu durumda 2. ve 3. sütunları kayan değerlere dönüştürmenin en iyi yolu nedir? DataFrame'e dönüştürürken türleri belirtmenin bir yolu var mı? Yoksa önce DataFrame'i oluşturmak ve ardından her sütunun türünü değiştirmek için sütunlar arasında döngü yapmak daha mı iyidir? İdeal olarak bunu dinamik bir şekilde yapmak istiyorum çünkü yüzlerce sütun olabilir ve tam olarak hangi sütunların hangi türde olduğunu belirtmek istemiyorum. Garanti edebileceğim tek şey, her sütunun aynı türde değerler içermesi.
Pandas'ta türleri dönüştürmek için üç ana seçeneğiniz vardır:
to_numeric()
- sayısal olmayan türleri (örn. dizeler) uygun bir sayısal türe güvenli bir şekilde dönüştürmek için işlevsellik sağlar. (Ayrıca bakınız to_datetime()
ve to_timedelta()
).to_numeric()
Bir DataFrame'in bir veya daha fazla sütununu sayısal değerlere dönüştürmenin en iyi yolu pandas.to_numeric()
kullanmaktır.
Bu fonksiyon, sayısal olmayan nesneleri (dizeler gibi) uygun şekilde tamsayılara veya kayan noktalı sayılara dönüştürmeye çalışacaktır.
to_numeric()` işlevinin girdisi bir Seri veya bir DataFrame'in tek bir sütunudur.
>>> s = pd.Series(["8", 6, "7.5", 3, "0.9"]) # mixed string and numeric values
>>> s
0 8
1 6
2 7.5
3 3
4 0.9
dtype: object
>>> pd.to_numeric(s) # convert everything to float values
0 8.0
1 6.0
2 7.5
3 3.0
4 0.9
dtype: float64
Gördüğünüz gibi, yeni bir Seri döndürülür. Kullanmaya devam etmek için bu çıktıyı bir değişkene veya sütun adına atamayı unutmayın:
# convert Series
my_series = pd.to_numeric(my_series)
# convert column "a" of a DataFrame
df["a"] = pd.to_numeric(df["a"])
Ayrıca, apply()
yöntemi aracılığıyla bir DataFrame'in birden çok sütununu dönüştürmek için de kullanabilirsiniz:
# convert all columns of DataFrame
df = df.apply(pd.to_numeric) # convert all columns of DataFrame
# convert just columns "a" and "b"
df[["a", "b"]] = df[["a", "b"]].apply(pd.to_numeric)
Değerlerinizin tümü dönüştürülebildiği sürece, muhtemelen ihtiyacınız olan tek şey budur.
Peki ya bazı değerler sayısal bir türe dönüştürülemiyorsa?
to_numeric()ayrıca sayısal olmayan değerleri
NaNolmaya zorlamanıza veya bu değerleri içeren sütunları yok saymanıza olanak tanıyan bir
errorsanahtar sözcük bağımsız değişkeni alır. Burada, nesne d türüne sahip bir dizi
s` dizesi kullanan bir örnek verilmiştir:
>>> s = pd.Series(['1', '2', '4.7', 'pandas', '10'])
>>> s
0 1
1 2
2 4.7
3 pandas
4 10
dtype: object
Varsayılan davranış, bir değeri dönüştüremezse yükseltmektir. Bu durumda, 'pandas' dizesi ile başa çıkamaz:
>>> pd.to_numeric(s) # or pd.to_numeric(s, errors='raise')
ValueError: Unable to parse string
Başarısız olmak yerine, 'pandas''ın eksik/kötü bir sayısal değer olarak kabul edilmesini isteyebiliriz. Geçersiz değerleri errors
anahtar kelime argümanını kullanarak aşağıdaki gibi NaN
'a zorlayabiliriz:
>>> pd.to_numeric(s, errors='coerce')
0 1.0
1 2.0
2 4.7
3 NaN
4 10.0
dtype: float64
Hatalar için üçüncü seçenek, geçersiz bir değerle karşılaşıldığında işlemi yok saymaktır:
>>> pd.to_numeric(s, errors='ignore')
# the original Series is returned untouched
Bu son seçenek özellikle tüm DataFrame'inizi dönüştürmek istediğinizde, ancak hangi sütunlarımızın güvenilir bir şekilde sayısal bir türe dönüştürülebileceğini bilmediğinizde kullanışlıdır. Bu durumda sadece yazın:
df.apply(pd.to_numeric, errors='ignore')
Fonksiyon, DataFrame'in her bir sütununa uygulanacaktır. Sayısal bir türe dönüştürülebilen sütunlar dönüştürülecek, dönüştürülemeyen sütunlar ise (örneğin, rakam içermeyen dizeler veya tarihler içeriyorlarsa) olduğu gibi bırakılacaktır.
Varsayılan olarak, to_numeric()
ile dönüşüm size bir int64
veya float64
dtype (veya platformunuz için yerel olan tamsayı genişliği) verecektir.
Bu genellikle istediğiniz şeydir, ancak ya biraz bellek tasarrufu yapmak ve float32
veya int8
gibi daha kompakt bir dtype kullanmak isterseniz?
to_numeric()size 'integer', 'signed', 'unsigned', 'float' türlerinden birine downcast yapma seçeneği sunar. İşte tamsayı tipinde basit bir
s` serisi için bir örnek:
>>> s = pd.Series([1, 2, -7])
>>> s
0 1
1 2
2 -7
dtype: int64
integer' 'a downcasting, değerleri tutabilecek mümkün olan en küçük integer'ı kullanır:
>>> pd.to_numeric(s, downcast='integer')
0 1
1 2
2 -7
dtype: int8
Benzer şekilde 'float''a downcasting normalden daha küçük bir kayan tip seçer:
>>> pd.to_numeric(s, downcast='float')
0 1.0
1 2.0
2 -7.0
dtype: float32
astype()
astype()`](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.astype.html) yöntemi, DataFrame veya Serinizin sahip olmasını istediğiniz dtype hakkında açık olmanızı sağlar. Bir türden diğerine geçmeyi deneyebilmeniz açısından çok yönlüdür.
Sadece bir tür seçin: bir NumPy türü (örneğin np.int16
), bazı Python türleri (örneğin bool) veya pandas'a özgü türleri (kategorik tür gibi) kullanabilirsiniz.
Dönüştürmek istediğiniz nesne üzerindeki yöntemi çağırın ve astype()
onu sizin için dönüştürmeye çalışacaktır:
# convert all DataFrame columns to the int64 dtype
df = df.astype(int)
# convert column "a" to int64 dtype and "b" to complex type
df = df.astype({"a": int, "b": complex})
# convert Series to float16 type
s = s.astype(np.float16)
# convert Series to Python strings
s = s.astype(str)
# convert Series to categorical type - see docs for more details
s = s.astype('category')
try" dediğime dikkat edin - eğer astype()
Seri veya DataFrame'deki bir değeri nasıl dönüştüreceğini bilmiyorsa, hata verecektir. Örneğin, bir NaN
veya inf
değeriniz varsa, bunu bir tamsayıya dönüştürmeye çalışırken bir hata alırsınız.
Pandas 0.20.0'dan itibaren, bu hata errors='ignore'
geçilerek bastırılabilir. Orijinal nesnenize dokunulmadan geri dönülecektir.
astype()` güçlüdür, ancak bazen değerleri "yanlış" dönüştürebilir. Örneğin:
>>> s = pd.Series([1, 2, -7])
>>> s
0 1
1 2
2 -7
dtype: int64
Bunlar küçük tamsayılardır, bu nedenle bellekten tasarruf etmek için işaretsiz 8 bitlik bir türe dönüştürmeye ne dersiniz?
>>> s.astype(np.uint8)
0 1
1 2
2 249
dtype: uint8
pd.to_numeric(s, downcast='unsigned')
kullanarak downcast yapmaya çalışmak bu hatayı önlemeye yardımcı olabilir.infer_objects()
Pandas'ın 0.21.0 sürümü, bir DataFrame'in nesne veri türüne sahip sütunlarını daha spesifik bir türe dönüştürmek için infer_objects()
yöntemini tanıttı (yumuşak dönüşümler).
Örneğin, burada nesne türünde iki sütunu olan bir DataFrame var. Biri gerçek tamsayıları, diğeri ise tamsayıları temsil eden dizeleri tutar:
>>> df = pd.DataFrame({'a': [7, 1, 5], 'b': ['3','2','1']}, dtype='object')
>>> df.dtypes
a object
b object
dtype: object
infer_objects()` fonksiyonunu kullanarak 'a' sütununun türünü int64 olarak değiştirebilirsiniz:
>>> df = df.infer_objects()
>>> df.dtypes
a int64
b object
dtype: object
Sütun 'b' değerleri tamsayı değil dizeler olduğu için yalnız bırakılmıştır. Her iki sütunun da tamsayı türüne dönüştürülmesini denemek ve zorlamak istiyorsanız, bunun yerine df.astype(int)
kullanabilirsiniz.
Buna ne dersin?
a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]
df = pd.DataFrame(a, columns=['one', 'two', 'three'])
df
Out[16]:
one two three
0 a 1.2 4.2
1 b 70 0.03
2 x 5 0
df.dtypes
Out[17]:
one object
two object
three object
df[['two', 'three']] = df[['two', 'three']].astype(float)
df.dtypes
Out[19]:
one object
two float64
three float64
Burada, argüman olarak bir DataFrame ve bir sütun listesi alan ve sütunlardaki tüm verileri sayılara zorlayan bir fonksiyon bulunmaktadır.
# df is the DataFrame, and column_list is a list of columns as strings (e.g ["col1","col2","col3"])
# dependencies: pandas
def coerce_df_columns_to_numeric(df, column_list):
df[column_list] = df[column_list].apply(pd.to_numeric, errors='coerce')
Yani, örneğiniz için:
import pandas as pd
def coerce_df_columns_to_numeric(df, column_list):
df[column_list] = df[column_list].apply(pd.to_numeric, errors='coerce')
a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]
df = pd.DataFrame(a, columns=['col1','col2','col3'])
coerce_df_columns_to_numeric(df, ['col2','col3'])