NumPy veya Pandalar: NaN değerine sahipken dizi türünü tam sayı olarak tutma


160

İçinde hala bir öğe listelenirken bir numpydizinin veri türünü int( int64veya herhangi bir şekilde) sabit tutmanın tercih edilen bir yolu var mı numpy.NaN?

Özellikle, bir şirket içi veri yapısını bir Pandas DataFrame'e dönüştürüyorum. Yapımızda, hala NaN'leri olan tamsayı tipi sütunlarımız var (ancak sütunun türü int'dir). Bunu bir DataFrame yaparsak, her şeyi bir şamandıra olarak yeniden ele alıyor gibi görünüyor, ama gerçekten olmak istiyoruz int.

Düşünceler?

Denenen şeyler:

from_records()PandaDataFrame altında işlevini kullanarak denedim coerce_float=Falseve bu yardımcı olmadı. Ayrıca, aynı zamanda çalışmadı NaN dolgu_değeri ile NumPy maskeli dizileri kullanarak çalıştı. Tüm bunlar sütun veri türünün bir kayan nokta olmasına neden oldu.


Numpy maskeli bir dizi kullanabilir misiniz?
mgilson

Bir deneyeyim. Ben de from_recordspanda.DataFrame altında fonksiyonu denedim coerce_float=False, ama şans yok ... hala yeni veri türü var yapar float64.
ely

1
Evet, şans yok. Maskelenmiş dizide bile, hala yüzmeye dönüşür. Görünüşe göre Pandalar şöyle gidiyor: "Her yerde bir NaN var mı? ... O zaman her şey bir şamandıra." Umarım bu konuda bir yol vardır.
ely

1
İ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 cevap bulun. pandalar 0.24.x sürüm notları
mork

Yanıtlar:


70

Bu özellik pandalara eklendi (0.24 sürümünden başlayarak): https://pandas.pydata.org/pandas-docs/version/0.24/whatsnew/v0.24.0.html#optional-integer-na-support

Bu noktada, varsayılan dtype int64 (küçük harf) yerine dtype Int64 (büyük harf) kullanılmasını gerektirir.


1
Şimdilik 'Int64'çalışmasını sağlamak için özel bir tür belirtmelisiniz . Varsayılan olarak etkinleştirileceği zaman daha da iyi olacaktır.
Jean Paul

Bu harika! Bununla birlikte, PyCharm'ın bu şekilde kullanılırsa veri çerçevesini hata ayıklama penceresinde görüntülememesine rağmen küçük bir sorun vardır. Görüntülemenin nasıl zorlanacağıyla ilgili başka bir soru için cevabımı görebilirsiniz: stackoverflow.com/questions/38956660/… (asıl sorun farklı, ancak veri çerçevesini görüntüleme çözümü)
Alaa M.

Kullanmam gerekiyor mu 'Int64'veya benzeri bir şey var 'Int8'mı? İle karşılaştırıldığında çılgınca bir hafıza kullanır np.float.
Superdooperhero

'Int8'çalışıyor gibi görünüyor, ancak np.floatyine de daha hızlı yükleniyor gibi görünüyor. Sorun, aralarında bellek bırakmıyor gibi görünüyor. Çöp toplayıcının sonunda çalışacağını varsayın.
Superdooperhero

103

NaNbir tamsayı dizisinde saklanamaz. Bu şu anda pandaların bilinen bir sınırlamasıdır; NumPy'deki NA değerleriyle (R'deki NA'lara benzer) ilerleme kaydedilmeyi bekliyorum, ancak NumPy bu özellikleri almadan en az 6 aydan bir yıla kadar olacak, öyle görünüyor:

http://pandas.pydata.org/pandas-docs/stable/gotchas.html#support-for-integer-na

(Bu özellik, pandaların 0.24 sürümünden başlayarak eklenmiştir, ancak varsayılan dtype int64 (küçük harf) yerine dtype Int64 (büyük harfli) uzantısının kullanılmasını gerektirdiğini unutmayın: https://pandas.pydata.org/pandas- dokümanlar / sürüm / 0.24 / whatsnew / v0.24.0.html # isteğe bağlı-tamsayı-na-destek )


7
Merhaba Wes, bu konuda herhangi bir güncelleme var mı? Birleştirilen sütunların, orijinal listede bir NA değerinin varlığına bağlı olarak, içe veya kayan sayılara dönüştürüldüğü sorunlarla karşılaşırız. (Daha sonra bu veri çerçevelerini birleştirmeye çalışırken sorunlar oluşturma)
Carst


8

Performans ana sorun değilse, bunun yerine dizeleri saklayabilirsiniz.

df.col = df.col.dropna().apply(lambda x: str(int(x)) )

Sonra istediğiniz kadar karıştırabilirsiniz NaN. Uygulamanıza bağlı olarak gerçekten tamsayılara sahip olmak istiyorsanız, temsil etmek için -1, veya 0, veya 1234567890veya başka bir özel değer kullanabilirsiniz.NaN .

Ayrıca, sütunları geçici olarak çoğaltabilirsiniz: bir tanesi sahip olduğunuz gibi, kayan noktalı; diğeri ise ints ya da stringlerle deneysel. Sonra assertsikisinin senkronize olduğunu kontrol ederek her makul yere yerleştirir. Yeterli testten sonra şamandıraları bırakabilirsiniz.


5

Bu tüm durumlar için bir çözüm değildir, ancak benimki (genomik koordinatlar) 0'ı NaN olarak kullanmaya başvurdum

a3['MapInfo'] = a3['MapInfo'].fillna(0).astype(int)

Bu, en azından uygun 'doğal' sütun türünün kullanılmasına izin verir, çıkarma, karşılaştırma vb. İşlemler beklendiği gibi çalışır


5

Pandalar v0.24 +

NaNTamsayı serilerinde destekleme işlevselliği v0.24'ten itibaren mevcut olacaktır. Orada bilgiler bu konuda altındaki bölüme ve daha fazla ayrıntı "Yenilikler" v0.24 içinde null tamsayı veri türü .

Pandalar v0.23 ve öncesi

Genelde, çalışmak en iyisidir floatserisi dan upcast bile mümkün, serinin intiçin floatsebebiyle dahil edilmesindenNaN değerler. Bu, aksi takdirde Python düzeyindeki döngülerin işleneceği vectorized NumPy tabanlı hesaplamaları mümkün kılar.

Belgeler şunu önermektedir : "Bir olasılık, dtype=objectdizileri kullanmaktır." Örneğin:

s = pd.Series([1, 2, 3, np.nan])

print(s.astype(object))

0      1
1      2
2      3
3    NaN
dtype: object

Kozmetik nedenlerle, bir dosyaya örneğin çıkışı, Bunun için mayıs tercih edilebilir.

Pandalar v0.23 ve öncesi: arka plan

NaNa olarak kabul edilirfloat . (V0.23 itibariyle) şu anda docs Integer serisi için upcasted edilir nedenini belirtin float:

NumPy'de sıfırdan yüksek performanslı NA desteğinin bulunmaması durumunda, birincil kayıp, NA'ları tamsayı dizilerinde temsil etme yeteneğidir.

Bu değiş tokuş büyük ölçüde bellek ve performans nedenleriyle yapılır ve sonuçta elde edilen Seriler “sayısal” olmaya devam eder.

Dokümanlar ayrıca içerme nedeniyle yayıncılık için kurallar sağlar NaN:

Typeclass   Promotion dtype for storing NAs
floating    no change
object      no change
integer     cast to float64
boolean     cast to object


1

Sadece yeni bir 'Int64' dtype dönüştürmek NA olan bir float (1.143) vektörü tamsayıya (1) dönüştürmeye çalışıyorsanız, size bir hata vereceğini eklemek istedim. Bunu çözmek için sayıları yuvarlayıp ".astype ('Int64')"

s1 = pd.Series([1.434, 2.343, np.nan])
#without round() the next line returns an error 
s1.astype('Int64')
#cannot safely cast non-equivalent float64 to int64
##with round() it works
s1.round().astype('Int64')
0      1
1      2
2    NaN
dtype: Int64

Benim kullanım durumum, int'e yuvarlamak istediğim bir şamandıra serim var, ancak .round () yaptığınızda sayının sonunda bir '* .0' kalır, böylece 0'ı sonuna kadar bırakabilirsiniz. int dönüştürülüyor.


0

Metin verilerinde boşluklar varsa, normalde tamsayı olacak sütunlar float64 dtype olarak kayan noktaya dönüştürülür, çünkü int64 dtype null'ları işleyemez. Bazıları boşluklu birden çok dosya yüklerseniz bu tutarsız şemaya neden olabilir (float64 ve diğerleri olmadan int64 olarak sonuçlanır.

Bu kod, herhangi bir sayı türü sütunu Int64'e (int64'ün aksine) dönüştürmeye çalışacaktır, çünkü Int64 null'ları işleyebilir

import pandas as pd
import numpy as np

#show datatypes before transformation
mydf.dtypes

for c in mydf.select_dtypes(np.number).columns:
    try:
        mydf[c] = mydf[c].astype('Int64')
        print('casted {} as Int64'.format(c))
    except:
        print('could not cast {} to Int64'.format(c))

#show datatypes after transformation
mydf.dtypes
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.