NaN içeren Pandalar sütununu dtype `int`


175

Aşağıdaki gibi .csv dosyasından bir Pandas veri çerçevesine veri okudum. Sütunlardan biri idiçin, sütun türünü belirtmek istiyorum int. Sorun, idserinin eksik / boş değerleri olmasıdır.

id.Csv dosyasını okurken sütunu tamsayıya dönüştürmeye çalıştığımda , şunu alıyorum:

df= pd.read_csv("data.csv", dtype={'id': int}) 
error: Integer column has NA values

Alternatif olarak, aşağıdaki gibi okuduktan sonra sütun türünü dönüştürmeye çalıştım, ancak bu sefer alıyorum:

df= pd.read_csv("data.csv") 
df[['id']] = df[['id']].astype(int)
error: Cannot convert NA to integer

Bununla nasıl başa çıkabilirim?


3
Eksik / NaN değerleri varsa tamsayı değerlerinin bir seri / veri çerçevesinde dönüştürülemediğini veya depolanamayacağını düşünüyorum. Bu değer uyumluluk ile yapmak olduğunu düşünüyorum (Ben burada tahmin ediyorum), eksik değer uyumluluğu istiyorsanız o zaman değerleri yüzen olarak depolamak istiyorum
EdChum

1
buraya bakınız: pandas.pydata.org/pandas-docs/dev/… ; u eksik değerlere sahip olduğunuzda (veya teknik olarak nesne dtype ama bu verimsiz) bir float dtype olmalıdır; int tipini kullanma amacınız nedir?
Jeff

6
Bunun bir NumPy sorunu olduğuna inanıyorum, Pandalara özgü değil. Null değer olasılığına olanak tanıyan bir int türüne sahip olduğunuzda, büyük bir yüzer sütundan çok daha verimli olduğu için çok utanç verici.
ely

1
Bununla da bir sorunum var. Birkaç "tamsayı" sütun bir dize temsili dayalı birleştirmek istediğiniz birden çok dataframes var. Ancak, bu tamsayı sütunlarından birinde bir np.nan varsa, dize döküm bir ".0" üretir, birleştirme atar. Sadece işleri biraz daha karmaşık hale getirir, basit bir çözüm olsaydı iyi olurdu.
dermen

1
@Rhubarb, İsteğe Bağlı Sıfırlanabilir Tam Sayı Desteği artık resmi olarak panda 0.24.0'a eklendi - sonunda :) - lütfen güncellenmiş bir yanıt bulun. pandalar 0.24.x sürüm notları
mork

Yanıtlar:


169

Tam sayı sütunlarında NaN temsilcisi olmaması bir panda "gotcha" dır .

Genel çözüm sadece şamandıra kullanmaktır.


13
Şamandıra gibi davranmanın yanı sıra başka geçici çözümler var mı?
NumenorForLife

3
@ jsc123 dtype nesnesini kullanabilirsiniz. Bu küçük bir sağlık uyarısı ile birlikte gelir, ancak çoğunlukla iyi çalışır.
Andy Hayden

1
Dtype nesnesinin nasıl kullanılacağına dair bir örnek verebilir misiniz? Pandalar belgelerine ve googling'e baktım ve önerilen yöntem olduğunu okudum. Ancak, dtype nesnesinin nasıl kullanılacağına dair bir örnek bulamadım.
MikeyE

29
V0.24'te artık yapabilirsiniz df = df.astype(pd.Int32Dtype())(dataFrame'in tamamını dönüştürmek için veya) df['col'] = df['col'].astype(pd.Int32Dtype()). Diğer kabul edilebilir null olabilecek tamsayı türleri pd.Int16Dtypeve pd.Int64Dtype. Zehirini seç.
cs95

1
NaN değeri ama isnan kontrolü hiç çalışmıyor :(
Winston

117

0.24 sürümünde. + Pandalar eksik değerlere sahip tamsayı tiplerini tutma kabiliyeti kazanmıştır.

Sıfırlanabilir Tam Sayı Veri Türü .

Pandalar, olası eksik değerleri olan tamsayı verilerini temsil edebilir arrays.IntegerArray. Bu, pandalar içinde uygulanan bir uzantı türüdür. Tamsayılar için varsayılan dtype değildir ve çıkarılmayacaktır; dtype'yi açık bir şekilde array()veya Series:

arr = pd.array([1, 2, np.nan], dtype=pd.Int64Dtype())
pd.Series(arr)

0      1
1      2
2    NaN
dtype: Int64

Sütunu boş sayılara dönüştürmek için şunu kullanın:

df['myCol'] = df['myCol'].astype('Int64')

4
Bu cevabı beğendim.
cs95

8
Dtype olması gerektiğini "Int64"ve olmamasını unutmayın "int64"(ilk 'i' büyük harfle yazılmalıdır)
Viacheslav Z

2
df.myCol = df.myCol.astype('Int64')veyadf['myCol'] = df['myCol'].astype('Int64')
LoMaPh

43

Benim kullanım durumum bir DB tabloya yüklemeden önce verileri munging olduğunu:

df[col] = df[col].fillna(-1)
df[col] = df[col].astype(int)
df[col] = df[col].astype(str)
df[col] = df[col].replace('-1', np.nan)

NaN'leri kaldırın, int'e dönüştürün, str'ye dönüştürün ve sonra NAN'ları yeniden takın.

Güzel değil ama işi hallediyor!


1
Bazıları null ve geri kalanı yüzen seri numaralarını yüklemeye çalışırken saçlarımı çekiyorum, bu beni kurtardı.
Chris Decker

1
OP bir tamsayı sütunu istiyor. Dizeye dönüştürmek koşulu karşılamıyor.
Rishab Gupta

1
Yalnızca col'da -1 yoksa çalışır. Aksi takdirde, verilerle
uğraşacak

sonra int .. geri almak için nasıl?
abdoulsn

5

Şimdi intpandalara 0.24.0 resmi olarak eklendiğinden , dtype olarak NaN içeren bir panda sütunu oluşturmak artık mümkün.

pandalar 0.24.x sürüm notları Alıntı: " Pandalar eksik değerlerle tamsayı dtypes tutma yeteneği kazandı


4

Tamsayıları ve NaN'leri bir sütunda kesinlikle birleştirmek istiyorsanız, 'nesne' veri türünü kullanabilirsiniz:

df['col'] = (
    df['col'].fillna(0)
    .astype(int)
    .astype(object)
    .where(df['col'].notnull())
)

Bu, NaN'leri bir tamsayı ile değiştirir (hangisi önemli değil), int'e dönüştürür, nesneye dönüştürür ve son olarak NaN'leri yeniden yerleştirir.


3

Saklanan verilerinizi değiştirebiliyorsanız, eksik olması için bir sentinel değeri kullanın id. Sütun adıyla çıkarılan id, tam olarak sıfırdan büyük bir tam sayı olması nedeniyle , 0yazabilmeniz için sentinel değeri olarak kullanabilirsiniz .

if row['id']:
   regular_process(row)
else:
   special_process(row)

3

.dropna()NaN değerleriyle satırları bırakmak uygunsa kullanabilirsiniz .

df = df.dropna(subset=['id'])

Alternatif olarak, kullanım .fillna()ve .astype()değerlerle NaN değiştirip int dönüştürmek için.

Bazıları eksikken (NaN) büyük tamsayılarla bir CSV dosyası işlerken bu sorunla karşılaştım. Şamandırayı tür olarak kullanmak bir seçenek değildi, çünkü hassasiyeti kaybedebilirim.

Benim çözümüm ara tip olarak str kullanmaktı . Daha sonra, daha sonra kodda istediğiniz gibi dizeyi int'e dönüştürebilirsiniz. NaN'yi 0 ile değiştirdim, ancak herhangi bir değer seçebilirsiniz.

df = pd.read_csv(filename, dtype={'id':str})
df["id"] = df["id"].fillna("0").astype(int)

Örnek olarak, şamandıraların hassasiyeti nasıl kaybedebileceğine dair bir örnek:

s = "12345678901234567890"
f = float(s)
i = int(f)
i2 = int(s)
print (f, i, i2)

Ve çıktı:

1.2345678901234567e+19 12345678901234567168 12345678901234567890

2

Buradaki çoğu çözüm null'ları temsil etmek için bir yer tutucu tamsayısının nasıl kullanılacağını anlatır. Ancak, tamsayıların kaynak verilerinizde görünmeyeceğinden emin değilseniz bu yaklaşım yararlı olmaz. Benim yöntem ile ondalık değerleri olmadan kayan biçimlendirir ve nulls yok's dönüştürür. Sonuç, bir CSV'ye yüklendiğinde boş değerlere sahip bir tamsayı alanına benzeyen bir nesne veri tipidir.

keep_df[col] = keep_df[col].apply(lambda x: None if pandas.isnull(x) else '{0:.0f}'.format(pandas.to_numeric(x)))

1

Bu konuda pyspark ile çalıştım. Bu bir jvm üzerinde çalışan kod için bir python ön ucu olduğundan, tür güvenliği gerektirir ve int yerine float kullanmak bir seçenek değildir. Pandalar pd.read_csv, kullanıcı tanımlı sütunları kullanıcı tanımlı doldurma değerleri ile dolduracak bir işleve gerekli türe dökmeden önce sararak sorunu çözdüm . İşte ben kullanarak sona erdi:

def custom_read_csv(file_path, custom_dtype = None, fill_values = None, **kwargs):
    if custom_dtype is None:
        return pd.read_csv(file_path, **kwargs)
    else:
        assert 'dtype' not in kwargs.keys()
        df = pd.read_csv(file_path, dtype = {}, **kwargs)
        for col, typ in custom_dtype.items():
            if fill_values is None or col not in fill_values.keys():
                fill_val = -1
            else:
                fill_val = fill_values[col]
            df[col] = df[col].fillna(fill_val).astype(typ)
    return df

1
import pandas as pd

df= pd.read_csv("data.csv")
df['id'] = pd.to_numeric(df['id'])

4
Bu formülasyonu kabul edilen cevapta önerilene göre tercih etmenizin bir nedeni var mı? Öyleyse, bu açıklamayı sağlamak için cevabınızı düzenlemek yararlı olacaktır - ve özellikle dikkat çekmek için rekabet eden on ek cevap olduğundan.
Jeremy Caney

Bu kod OP'nin sorununu çözse de, kodunuzun buna nasıl / neden hitap ettiği hakkında bir açıklama eklemek en iyisidir. Bu şekilde, gelecekteki ziyaretçiler yayınınızdan bilgi edinebilir ve kendi kodlarına uygulayabilir. SO bir kodlama servisi değil, bilgi kaynağıdır. Ayrıca, yüksek kaliteli ve eksiksiz cevapların kaldırılması daha olasıdır. Bu özellikler, tüm yayınların bağımsız olması şartıyla birlikte, bir platform onu ​​forumlardan farklılaştırdığı için SO'nun güçlü yönlerinden bazılarıdır. Şunları yapabilirsiniz editek bilgi eklemek ve / veya kaynak belgelerle açıklamalarının tamamlamak için.
SherylHohman

0

Önce NaN içeren satırları kaldırın. Sonra kalan satırlarda Tamsayı dönüştürme yapın. Sonunda kaldırılan satırları tekrar ekleyin. Umarım işe yarar


-1

3312018.0 biçimindeki DateColumn'unuzun dize olarak 03/31/2018 biçimine dönüştürülmesi gerekir. Ve bazı kayıtlar eksik veya 0.

df['DateColumn'] = df['DateColumn'].astype(int)
df['DateColumn'] = df['DateColumn'].astype(str)
df['DateColumn'] = df['DateColumn'].apply(lambda x: x.zfill(8))
df.loc[df['DateColumn'] == '00000000','DateColumn'] = '01011980'
df['DateColumn'] = pd.to_datetime(df['DateColumn'], format="%m%d%Y")
df['DateColumn'] = df['DateColumn'].apply(lambda x: x.strftime('%m/%d/%Y'))
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.