Pandalar kullanarak “büyük veri” iş akışları


980

Panda öğrenirken aylarca bu sorunun cevabını bulmaya çalıştım. SAS'ı günlük işlerim için kullanıyorum ve çekirdek dışı desteği için harika. Bununla birlikte, SAS, başka birçok nedenden dolayı bir yazılım parçası olarak korkunçtur.

Bir gün SAS kullanımımı python ve pandalarla değiştirmeyi umuyorum, ancak şu anda büyük veri kümeleri için çekirdek dışı bir iş akışından yoksunum. Dağıtılmış bir ağ gerektiren "büyük veri" den bahsetmiyorum, daha ziyade belleğe sığmayacak kadar büyük ancak bir sabit sürücüye sığacak kadar küçük dosyalar.

İlk düşüncem, HDFStorebüyük veri kümelerini diskte tutmak ve yalnızca ihtiyaç duyduğum parçaları analiz için veri çerçevelerine çekmek. Diğerleri MongoDB'yi kullanımı daha kolay bir alternatif olarak belirtmiştir. Sorum şu:

Aşağıdakileri gerçekleştirmek için en iyi uygulama iş akışları nelerdir:

  1. Düz dosyaları kalıcı bir disk üstü veritabanı yapısına yükleme
  2. Panda veri yapısına beslenecek verileri almak için bu veritabanını sorgulama
  3. Pandalarda parçaları işledikten sonra veritabanını güncelleme

Gerçek dünya örnekleri, özellikle "büyük veriler" üzerinde panda kullanan herkes için çok takdir edilecektir.

Düzenle - bunun nasıl çalışmasını istediğinize bir örnek:

  1. Büyük bir düz dosyayı aralıksız olarak içe aktarın ve kalıcı, disk üstü veritabanı yapısında saklayın. Bu dosyalar genellikle belleğe sığmayacak kadar büyüktür.
  2. Pandaları kullanmak için, bu verilerin belleğe sığabilecek alt kümelerini (genellikle bir seferde sadece birkaç sütun) okumak istiyorum.
  3. Seçilen sütunlarda çeşitli işlemler yaparak yeni sütunlar oluşturabilirim.
  4. Sonra bu yeni sütunları veritabanı yapısına eklemek zorunda kalacak.

Bu adımları gerçekleştirmenin en iyi yolunu bulmaya çalışıyorum. Pandalar ve pire ile ilgili bağlantıları okumak, yeni bir sütun eklemenin bir sorun olabileceği görülüyor.

Edit - Jeff'in sorularına özellikle cevap vermek:

  1. Tüketici kredi riski modelleri oluşturuyorum. Veri türleri telefon, SSN ve adres özelliklerini; mülk değerleri; Adli sicil kayıtları, iflaslar, vs. gibi aşağılayıcı bilgiler ... Her gün kullandığım veri kümelerinin, ortalama olarak sayısal ve karakter verilerinin sürekli, nominal ve sıra değişkenleri olmak üzere ortalama karışık veri türlerinde yaklaşık 1.000 ila 2.000 alanı vardır. Nadiren satır ekliyorum, ancak yeni sütunlar oluşturan birçok işlem gerçekleştiriyorum.
  2. Tipik işlemler, koşullu mantık kullanarak birkaç sütunun yeni bir bileşik sütunda birleştirilmesini içerir. Örneğin if var1 > 2 then newvar = 'A' elif var2 = 4 then newvar = 'B',. Bu işlemlerin sonucu, veri kümemdeki her kayıt için yeni bir sütundur.
  3. Son olarak, bu yeni sütunları diskteki veri yapısına eklemek istiyorum. Model için ilginç, sezgisel ilişkiler bulmaya çalışan verileri çapraz tablolar ve açıklayıcı istatistikler ile inceleyerek 2. adımı tekrar ediyorum.
  4. Tipik bir proje dosyası genellikle yaklaşık 1 GB'dir. Dosyalar, bir satırın tüketici verilerinin bir kaydını içereceği şekilde düzenlenir. Her satır, her kayıt için aynı sayıda sütuna sahiptir. Her zaman böyle olacak.
  5. Yeni bir sütun oluştururken satırlara göre alt kümeler oluşturmak oldukça nadirdir. Ancak, rapor oluştururken veya açıklayıcı istatistikler oluştururken satırları alt kümelere ayırmak benim için oldukça yaygın. Örneğin, Perakende kredi kartları gibi belirli bir iş kolu için basit bir sıklık oluşturmak isteyebilirim. Bunu yapmak için, hangi satırları rapor etmek istediğime ek olarak yalnızca iş kolunun = perakende olduğu kayıtları seçerim. Ancak, yeni sütunlar oluştururken, tüm veri satırlarını ve yalnızca işlemler için ihtiyacım olan sütunları çekerdim.
  6. Modelleme süreci, her sütunu analiz etmemi, bazı sonuç değişkenleriyle ilginç ilişkiler aramamı ve bu ilişkileri tanımlayan yeni bileşik sütunlar oluşturmamı gerektirir. Keşfettiğim sütunlar genellikle küçük setler halinde yapılır. Örneğin, sadece mülk değerleri ile ilgilenen bir dizi 20 sütuna odaklanacağım ve bunların bir kredinin temerrüde düşme ile nasıl ilişkili olduğunu gözlemleyeceğim. Bunlar keşfedildikten ve yeni sütunlar oluşturulduktan sonra, başka bir sütun grubuna geçiyorum, üniversite eğitimi diyorum ve süreci tekrar ediyorum. Yaptığım şey verilerim ve bazı sonuçlar arasındaki ilişkiyi açıklayan aday değişkenler oluşturmak. Bu sürecin sonunda, bu bileşik sütunlardan bir denklem oluşturan bazı öğrenme tekniklerini uyguluyorum.

Veri kümesine hiç satır eklemem nadirdir. Neredeyse her zaman yeni sütunlar yaratacağım (istatistik / makine öğrenimi konusundaki değişkenler veya özellikler).


1
Oran çekirdek boyutu / tam boyut% 1,% 10 mu? Önemli mi - eğer kömürleri int8'e sıkıştırabilirseniz veya gürültülü satırları filtreleyebilirseniz, bu hesaplama-düşünme döngünüzü saatlerden dakikalara değiştirir mi? (Ayrıca büyük veri etiketi ekleyin.)
denis

1
Float64 ve int8 yerine float32 depolamak önemsiz olmalıdır (hangi araçların / fonksiyonların dahili olarak float64 yaptığını bilmiyorum)
denis

görevinizi iş parçalarına ayırabilir misiniz?
Andrew Scott Evans

1
belleğe sığmayan "orta" veriler üzerinde panda gibi işlemler yapmak için güzel bir 2019 çözümü dask
lunguini

Yeni başladığınızda görmeyi düşünebileceğiniz python + pandalara alternatifler var. Python'un genel amaçlı bir programlama dili (veri tarama ve analiz için bir DSL değil) ve pandaların bunun üzerine işlenmiş bir kütüphane olduğunu düşünün. R veya kdb'ye bakmayı düşünürüm.
Henry Henrinson

Yanıtlar:


621

Düzenli olarak onlarca gigabayt veri kullanıyorum, örneğin diskler üzerinde sorguları okuduğum, veri oluşturduğum ve geri eklediğim tablolarım var.

Verilerinizi nasıl saklayacağınıza dair birkaç öneri için dokümanları okumaya ve bu iş parçacığının sonlarına değmeye değer .

Verilerinizi nasıl depolayacağınızı etkileyecek ayrıntılar , örneğin:
Mümkün olduğunca çok ayrıntı verin; ve bir yapı geliştirmenize yardımcı olabilirim.

  1. Veri boyutu, satır sayısı, sütunlar, sütun türleri; satır mı yoksa sadece sütun mu ekliyorsunuz?
  2. Tipik operasyonlar nasıl görünecek. Örneğin, bir grup satır ve belirli sütun seçmek için sütunlarda bir sorgu yapın, ardından bir işlem (bellek içi) yapın, yeni sütunlar oluşturun, bunları kaydedin.
    (Oyuncak örneği vermek, daha spesifik önerilerde bulunmamızı sağlayabilir.)
  3. Bu işlemden sonra ne yaparsınız? 2. adım ad hoc veya tekrarlanabilir mi?
  4. Düz dosyaları girin: Gb cinsinden toplam kaba boyut. Bunlar örneğin kayıtlarla nasıl düzenlenir? Her biri farklı alanlar içeriyor mu veya her dosyadaki tüm alanlarla birlikte dosya başına bazı kayıtları var mı?
  5. Ölçütlere göre hiç satır alt kümesini (kayıt) seçtiniz mi (örneğin, A> 5 alanına sahip satırları seçin)? ve sonra bir şey yapın, ya da sadece tüm kayıtların bulunduğu A, B, C alanlarını mı seçiyorsunuz (ve sonra bir şeyler yapıyorsunuz)?
  6. Tüm sütunlarınızda (gruplar halinde) 'çalışıyorsunuz' veya yalnızca raporlar için kullanabileceğiniz iyi bir oran var mı (örneğin, verileri saklamak istiyorsunuz, ancak bu sütun açıklığını çekmenize gerek yok) nihai sonuç süresi)?

Çözüm

En azından pandaların0.10.1 kurulu olduğundan emin ol .

Yinelenen dosyaları ve çoklu tablo sorgularını yineleme dosyalarını okuyun .

Pire'ler satır bazında (sorguladığınız şey) çalışmak üzere optimize edildiğinden, her alan grubu için bir tablo oluşturacağız. Bu şekilde küçük bir grup alan seçmek kolaydır (bu büyük bir tabloyla çalışacaktır, ancak bu şekilde yapmak daha verimlidir ... Bence bu sınırlamayı gelecekte çözebilirim ... bu nasıl olsa daha sezgisel):
(Aşağıdaki sözde koddur.)

import numpy as np
import pandas as pd

# create a store
store = pd.HDFStore('mystore.h5')

# this is the key to your storage:
#    this maps your fields to a specific group, and defines 
#    what you want to have as data_columns.
#    you might want to create a nice class wrapping this
#    (as you will want to have this map and its inversion)  
group_map = dict(
    A = dict(fields = ['field_1','field_2',.....], dc = ['field_1',....,'field_5']),
    B = dict(fields = ['field_10',......        ], dc = ['field_10']),
    .....
    REPORTING_ONLY = dict(fields = ['field_1000','field_1001',...], dc = []),

)

group_map_inverted = dict()
for g, v in group_map.items():
    group_map_inverted.update(dict([ (f,g) for f in v['fields'] ]))

Dosyalarda okuma ve depolama alanı oluşturma (temelde ne append_to_multipleyapıyor):

for f in files:
   # read in the file, additional options may be necessary here
   # the chunksize is not strictly necessary, you may be able to slurp each 
   # file into memory in which case just eliminate this part of the loop 
   # (you can also change chunksize if necessary)
   for chunk in pd.read_table(f, chunksize=50000):
       # we are going to append to each table by group
       # we are not going to create indexes at this time
       # but we *ARE* going to create (some) data_columns

       # figure out the field groupings
       for g, v in group_map.items():
             # create the frame for this group
             frame = chunk.reindex(columns = v['fields'], copy = False)    

             # append it
             store.append(g, frame, index=False, data_columns = v['dc'])

Şimdi dosyadaki tüm tablolara sahipsiniz (aslında isterseniz bunları ayrı dosyalarda saklayabilirsiniz, dosya adını group_map dosyasına eklemeniz gerekir, ancak muhtemelen bu gerekli değildir).

Sütunları bu şekilde elde edersiniz ve yeni sütunlar oluşturun:

frame = store.select(group_that_I_want)
# you can optionally specify:
# columns = a list of the columns IN THAT GROUP (if you wanted to
#     select only say 3 out of the 20 columns in this sub-table)
# and a where clause if you want a subset of the rows

# do calculations on this frame
new_frame = cool_function_on_frame(frame)

# to 'add columns', create a new group (you probably want to
# limit the columns in this new_group to be only NEW ones
# (e.g. so you don't overlap from the other tables)
# add this info to the group_map
store.append(new_group, new_frame.reindex(columns = new_columns_created, copy = False), data_columns = new_columns_created)

Post_processing için hazır olduğunuzda:

# This may be a bit tricky; and depends what you are actually doing.
# I may need to modify this function to be a bit more general:
report_data = store.select_as_multiple([groups_1,groups_2,.....], where =['field_1>0', 'field_1000=foo'], selector = group_1)

Data_columns hakkında, aslında herhangi bir data_columns tanımlamanız gerekmez; sütuna göre satırları alt seçmenize izin verir. Örneğin:

store.select(group, where = ['field_1000=foo', 'field_1001>0'])

Son rapor oluşturma aşamasında sizin için en ilgi çekici olabilirler (esasen bir veri sütunu diğer sütunlardan ayrılır, bu da çok fazla tanımlarsanız verimliliği biraz etkileyebilir).

Ayrıca şunları da yapmak isteyebilirsiniz:

  • alanların bir listesini alan, groups_map içindeki grupları arar, sonra bunları seçer ve sonuçları birleştirerek elde edilen kareyi elde edersiniz (esas olarak select_as_multiple budur). Bu şekilde yapı sizin için oldukça şeffaf olacaktır.
  • Belirli veri sütunlarındaki dizinler (satır alt kümesini çok daha hızlı hale getirir).
  • sıkıştırmayı etkinleştir.

Sorularınız olduğunda bana bildirin!


5
Bağlantılar için teşekkürler. İkinci bağlantı, HDFStore'daki tablolara yeni sütun ekleyemediğim için beni biraz endişelendiriyor mu? Bu doğru mu? Ayrıca, bu kurulumu nasıl kullanacağımı gösteren bir örnek ekledim.
Zelazny7

4
HDF'deki gerçek yapı size kalmış. Pire oluşturma sırasında sabit sütunlar ile satır odaklı. Bir tablo oluşturulduktan sonra sütun ekleyemezsiniz. Ancak, mevcut tablonuzla aynı dizine eklenmiş yeni bir tablo oluşturabilirsiniz. (dokümanlardaki select_as_multiple örneklerine bakın). Bu şekilde, oldukça verimli sorgular elde ederken rastgele boyutlu nesneler oluşturabilirsiniz. Verileri kullanma şekliniz, diskte nasıl organize edilmesi gerektiğinin anahtarıdır. Daha özel bir örneğin sahte kodunu içeren liste dışı bir e-posta gönder.
Jeff

1
Ayrıntılı noktalarınıza cevap vermek için sorumu güncelledim. Sizi liste dışı göndermek için bir örnek üzerinde çalışacağım. Teşekkürler!
Zelazny7

12
@Jeff, Pandaların 0.17.x'de olmasıyla, şimdi yukarıda açıklanan sorunlar Pandalar'da çözüldü mü?
ctrl-alt-delete

5
@ Jeff, dask'ı tanıtmak için cevabınıza hızlı bir güncelleme eklemeye hevesli misiniz?
Boud

137

Bence yukarıdaki cevaplar çok faydalı bulduğum basit bir yaklaşımı kaçırıyor.

Belleğe yüklenemeyecek kadar büyük bir dosyam olduğunda, dosyayı birden çok küçük dosyaya bölerim (satır veya sütunlarla)

Örnek: ~ 30GB büyüklüğünde 30 günlük işlem verisi olması durumunda, günde ~ 1GB büyüklüğünde bir dosyaya bölerim. Daha sonra her dosyayı ayrı ayrı işlerim ve sonunda sonuçları toplarım

En büyük avantajlardan biri, dosyaların paralel işlenmesine izin vermesidir (çoklu iş parçacıkları veya işlemler)

Diğer avantaj, dosya manipülasyonunun (örnekteki tarihlerin eklenmesi / kaldırılması gibi), daha gelişmiş / karmaşık dosya formatlarında mümkün olmayan normal kabuk komutlarıyla gerçekleştirilebilmesidir.

Bu yaklaşım tüm senaryoları kapsamaz, ancak birçoğunda çok yararlıdır




66

Veri kümeleriniz 1 ile 20 GB arasındaysa, 48 GB RAM'e sahip bir iş istasyonu almalısınız. Ardından Pandalar tüm veri kümesini RAM'de tutabilir. Burada aradığınız cevap olmadığını biliyorum, ancak 4GB RAM ile bir dizüstü bilgisayarda bilimsel bilgi işlem yapmak makul değildir.


7
"4GB RAM içeren bir dizüstü bilgisayarda bilimsel bilgi işlem yapmak makul değildir" Makul tanımlayın. Bence UNIVAC farklı bir görüş alacaktı. arstechnica.com/tech-policy/2011/09/…
grisaitis

2
Kabul! ön maliyeti $ olsa bile bellekte çalışmaya devam etmeyi deneyin. İşiniz finansal bir getiriye yol açıyorsa, zamanla, artan verimliliğiniz yoluyla masrafları geri alırsınız.
ansonw

2
48 GB RAM ile bir iş istasyonunda bilimsel bilgi işlem yapmak makul değildir.
Yaroslav Nikitenko

4
@YaroslavNikitenko 61GB / RAM ile bir r4.2xlarge $ 0532 / saat. Ne kadar bilimsel bilgi işlem yapıyorsunuz, bu değerli değil mi? Mantıksız değilse, olağandışı geliyor.
rjurney

4
@rjurney üzgünüm, belki de yorumumu silmeliydim. "Makul olmayan" bilimsel bilgisayar hakkındaki kararınız çok öznel görünüyor. Bilimsel hesaplamalarımı dizüstü bilgisayarlarda yıllarca yapıyorum ve bu benim için yeterli görünüyor, çünkü çoğu zaman kod yazıyorum. Algoritmalarım programlama açısından hesaplamaya göre çok daha zordur. Ayrıca ölçeklenebilir algoritmalar yazmak için mevcut donanım sınırlamalarına güvenmemeli eminim. Diğer kişilerin bilgi işlemine ilişkin yorumunuz (öznellik dışında) biraz rahatsız edici gelebilir, bu birkaç kelimeyi silebilir misiniz?
Yaroslav Nikitenko

58

Bu eski bir iş parçacığı olduğunu biliyorum ama Blaze kütüphane kontrol değer olduğunu düşünüyorum . Bu tür durumlar için üretilmiştir.

Dokümanlardan:

Blaze, NumPy ve Pandaların kullanılabilirliğini dağıtılmış ve çekirdek dışı bilgi işlem için genişletir. Blaze, NumPy ND-Array veya Pandas DataFrame'inkine benzer bir arayüz sağlar, ancak bu tanıdık arayüzleri Postgres veya Spark gibi diğer hesaplama motorlarına eşler.

Düzenleme: Bu arada, NumPy'nin yazarı ContinuumIO ve Travis Oliphant tarafından destekleniyor.


Bakmaya değer başka bir kütüphane GraphLab Create: Bellek kapasitesi ile sınırlı olmayan verimli bir DataFrame benzeri yapıya sahiptir. blog.dato.com/…
su geçirmez

52

Pymongo için durum böyledir. Ben de python sql sunucusu, sqlite, HDF, ORM (SQLAlchemy) kullanarak prototip var. İlk ve en önemlisi pymongo belge tabanlı bir DB'dir, bu nedenle her kişi ( dictniteliklerin) bir belgesi olacaktır . Birçok kişi bir koleksiyon oluşturur ve birçok koleksiyonunuz olabilir (insanlar, borsa, gelir).

pd.dateframe -> pymongo Not: Kullandığım chunksizeiçinde read_csv5 10k için kayıtlar (pymongo daha büyük ise soket düşer) onu tutmak için

aCollection.insert((a[1].to_dict() for a in df.iterrows()))

sorgulama: gt = şundan büyük ...

pd.DataFrame(list(mongoCollection.find({'anAttribute':{'$gt':2887000, '$lt':2889000}})))

.find()genellikle ichunkeddaha küçük yineleyiciler doğramak için kullanmak bir yineleyici döndürür .

Normalde bir araya getirmek için 10 veri kaynağı aldığımdan beri bir katılmaya ne dersiniz:

aJoinDF = pandas.DataFrame(list(mongoCollection.find({'anAttribute':{'$in':Att_Keys}})))

sonra (benim durumumda bazen aJoinDF"birleştirilebilir" önce önce agg gerekir .)

df = pandas.merge(df, aJoinDF, on=aKey, how='left')

Ardından, yeni bilgileri aşağıdaki güncelleme yöntemini kullanarak ana koleksiyonunuza yazabilirsiniz. (fiziksel veri kaynaklarına karşı mantıksal toplama).

collection.update({primarykey:foo},{key:change})

Daha küçük aramalarda sadece denormalize edin. Örneğin, belgede kodunuz vardır ve yalnızca alan kodu metnini ekler ve dictbelge oluştururken bir arama yaparsınız .

Artık bir kişi etrafında güzel bir veri kümeniz var, her durumda mantığınızı açığa çıkarabilir ve daha fazla özellik oluşturabilirsiniz. Sonunda 3 hafıza bellek göstergeleri pandalar okumak ve pivot / agg / veri keşif yapabilirsiniz. Bu benim için rakamlar / büyük metin / kategoriler / kodlar / şamandıralar / ...

MongoDB'de yerleşik iki yöntemi de kullanabilirsiniz (MapReduce ve aggregate framework). Toplam çerçeve hakkında daha fazla bilgi için buraya bakın , çünkü MapReduce'dan daha kolay görünüyor ve hızlı toplu çalışma için kullanışlı görünüyor. Alanlarımı veya ilişkilerimi tanımlamam gerekmediğine ve bir belgeye öğe ekleyebileceğime dikkat edin. Hızla değişen numpy, pandalar, python araç setinin mevcut durumunda, MongoDB sadece işe gitmeme yardımcı oluyor :)


Merhaba, ben de senin örnekle etrafında oynuyorum ve bir veritabanına eklemek çalışırken bu hata çıkıyor: In [96]: test.insert((a[1].to_dict() for a in df.iterrows())) --------------- InvalidDocument: Cannot encode object: 0. neyin yanlış olabileceğine dair bir fikri olan? Veri çerçevem ​​tüm int64 türlerinden oluşur ve çok basittir.
Zelazny7

2
Evet aynı şeyi basit bir aralık DF için yaptım ve numpy int64 pymongo rahatsız gibi görünüyor. Oynadığım tüm veriler CSV'den (yapay olarak aralık () aracılığıyla) dönüştürür ve uzun tiplere sahiptir ve bu nedenle sorun yoktur. Numpy'de dönüştürebilirsiniz ama bunu küçümseyen olarak görüyorum. HDF'nin heyecan verici görünmesi için 10.1 öğeyi itiraf etmeliyim.
brian_the_bungler

43

Bunu biraz geç fark ettim, ancak benzer bir problemle çalışıyorum (ipotek ön ödeme modelleri). Benim çözümüm pandalar HDFStore katmanını atlamak ve düz pire kullanmaktı. Her sütunu nihai dosyama ayrı bir HDF5 dizisi olarak kaydediyorum.

Temel iş akışım önce veritabanından bir CSV dosyası almak. Ben gzip, o kadar büyük değil. Sonra bunu python içinde yineleyerek, her satırı gerçek bir veri türüne dönüştürerek ve bir HDF5 dosyasına yazarak bir satır odaklı HDF5 dosyasına dönüştürüyorum. Bu onlarca dakika sürer, ancak sadece satır satır çalıştığı için bellek kullanmaz. Sonra satır yönelimli HDF5 dosyasını sütun yönelimli bir HDF5 dosyasına "aktarıyorum".

Tablo devri şuna benzer:

def transpose_table(h_in, table_path, h_out, group_name="data", group_path="/"):
    # Get a reference to the input data.
    tb = h_in.getNode(table_path)
    # Create the output group to hold the columns.
    grp = h_out.createGroup(group_path, group_name, filters=tables.Filters(complevel=1))
    for col_name in tb.colnames:
        logger.debug("Processing %s", col_name)
        # Get the data.
        col_data = tb.col(col_name)
        # Create the output array.
        arr = h_out.createCArray(grp,
                                 col_name,
                                 tables.Atom.from_dtype(col_data.dtype),
                                 col_data.shape)
        # Store the data.
        arr[:] = col_data
    h_out.flush()

Sonra tekrar okumak şöyle görünür:

def read_hdf5(hdf5_path, group_path="/data", columns=None):
    """Read a transposed data set from a HDF5 file."""
    if isinstance(hdf5_path, tables.file.File):
        hf = hdf5_path
    else:
        hf = tables.openFile(hdf5_path)

    grp = hf.getNode(group_path)
    if columns is None:
        data = [(child.name, child[:]) for child in grp]
    else:
        data = [(child.name, child[:]) for child in grp if child.name in columns]

    # Convert any float32 columns to float64 for processing.
    for i in range(len(data)):
        name, vec = data[i]
        if vec.dtype == np.float32:
            data[i] = (name, vec.astype(np.float64))

    if not isinstance(hdf5_path, tables.file.File):
        hf.close()
    return pd.DataFrame.from_items(data)

Şimdi, bunu genellikle tonlarca belleğe sahip bir makinede çalıştırıyorum, bu yüzden bellek kullanımım konusunda yeterince dikkatli olmayabilirim. Örneğin, yükleme işlemi varsayılan olarak tüm veri kümesini okur.

Bu genellikle benim için işe yarıyor, ama biraz tıknaz ve süslü pire sihrini kullanamıyorum.

Düzenleme: Bu yaklaşımın gerçek avantajı, kayıtlar dizi pytables varsayılan üzerinde, sonra tabloları işleyemez h5r kullanarak R içine veri yükleyebilirsiniz olmasıdır. Ya da en azından heterojen tablolar yükleyemedim.


bazı kodlarınızı benimle paylaşmak ister misiniz? Ben pire itmeden önce veri türlerini bilmeden bazı düz metin biçiminden veri yüklemek ilgilendi. Ayrıca, yalnızca bir tür verilerle çalıştığınız anlaşılıyor. Bu doğru mu?
13

1
Her şeyden önce, veriyi tahmin etmeye çalışmak yerine, yüklemeden önce sütun türlerini bildiğimi varsayıyorum. Bir JSON "veri spec" dosyasını sütun adları ve türleri ile kaydediyorum ve veri işlerken bunu kullanıyorum. (Dosya genellikle etiketi olmayan korkunç bir BCP çıktısıdır.) Kullandığım veri türleri dizeler, kayan noktalar, tamsayılar veya aylık tarihlerdir. Bir numaralandırma tablosu kaydedip tarihleri ​​ints'e (2000'i geçen aylar) dönüştürerek dizeleri ints'e dönüştürdüm, bu yüzden verilerimde ints ve floats, artı numaralandırma ile bıraktım. Şamandıraları float64 olarak kaydediyorum, ancak float32 ile denedim.
Johann Hibschman

1
Zamanınız varsa, lütfen bunu R: pandas.pydata.org/pandas-docs/dev/… ile harici uyumluluk için bir deneyin ve zorluk yaşıyorsanız, belki de ayarlayabiliriz
Jeff

Deneyebilirim, eğer yapabilirsem. rhdf5 bir acıdır, çünkü h5r gibi CRAN'da olmaktan ziyade bir biyo iletken pakettir. Teknik mimari ekibimizin merhametindeyim ve son istediğimde rhdf5 ile ilgili bir sorun vardı. Her halükarda, bir OLAP mağazası ile sütun odaklı olmak yerine satır odaklı gitmek bir hata gibi görünüyor, ama şimdi başıboş dolaşıyorum.
Johann Hibschman

38

Büyük veri kullanım durumları için yararlı bulduğum bir numara , şamandıra hassasiyetini 32 bit'e düşürerek veri hacmini azaltmaktır. Her durumda geçerli değildir, ancak birçok uygulamada 64 bit hassasiyet aşırıdır ve 2x bellek tasarrufu buna değer. Açık bir noktayı daha da belirgin hale getirmek için:

>>> df = pd.DataFrame(np.random.randn(int(1e8), 5))
>>> df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100000000 entries, 0 to 99999999
Data columns (total 5 columns):
...
dtypes: float64(5)
memory usage: 3.7 GB

>>> df.astype(np.float32).info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100000000 entries, 0 to 99999999
Data columns (total 5 columns):
...
dtypes: float32(5)
memory usage: 1.9 GB

26

Başkaları tarafından belirtildiği gibi, birkaç yıl sonra 'çekirdek dışı' panda eşdeğeri ortaya çıktı: dask . Dask, pandaların ve tüm işlevlerinin bir damla yerine geçmese de, çeşitli nedenlerle öne çıkıyor:

Dask, paralel diziler, veri çerçeveleri ve NumPy, Pandalar veya Python yineleyicileri gibi ortak arabirimleri daha geniş bir alana genişleten “Büyük Veri” koleksiyonlarının etkileşimli hesaplama iş yükleri için dinamik görev zamanlaması için optimize edilmiş analitik bilgi işlem için esnek bir paralel bilgi işlem kitaplığıdır. bellek veya dağıtılmış ortamlar ve dizüstü bilgisayarlardan kümelere kadar ölçeklendirilir.

Dask aşağıdaki erdemleri vurgular:

  • Tanıdık: Paralel NumPy dizisi ve Pandalar DataFrame nesneleri sağlar
  • Esnek: Daha özel iş yükleri ve diğer projelerle entegrasyon için bir görev zamanlama arabirimi sağlar.
  • Yerel: Pure Python'da dağıtılmış bilgi işlemin PyData yığınına erişmesini sağlar.
  • Hızlı: Hızlı sayısal algoritmalar için düşük ek yük, düşük gecikme süresi ve minimum serileştirme ile çalışır
  • Ölçekler: 1000'er çekirdek içeren kümelerde esnek bir şekilde çalışır Ölçekler: Tek bir işlemle bir dizüstü bilgisayarda kurulum ve çalıştırma önemsizdir
  • Duyarlı: Etkileşimli bilgi işlem göz önünde bulundurularak tasarlanan, insanlara yardımcı olmak için hızlı geri bildirim ve tanılama sağlar

ve basit bir kod örneği eklemek için:

import dask.dataframe as dd
df = dd.read_csv('2015-*-*.csv')
df.groupby(df.user_id).value.mean().compute()

bunun gibi bazı panda kodlarının yerini alır:

import pandas as pd
df = pd.read_csv('2015-01-01.csv')
df.groupby(df.user_id).value.mean()

ve özellikle dikkate değer şekilde, concurrent.futuresarayüz yoluyla özel görevlerin sunulması için genel bir altyapı sağlar:

from dask.distributed import Client
client = Client('scheduler:port')

futures = []
for fn in filenames:
    future = client.submit(load, fn)
    futures.append(future)

summary = client.submit(summarize, futures)
summary.result()

@Private'ın içeriği, içerik ve uzunluk için önerilen silinme listesinde düzenli olarak göründüğünden bu yanıtı ekledim.
wp78de

17

Burada Ray'den de bahsetmeye değer ,
bu pandalar için dağıtılmış bir şekilde kendi uygulaması olan dağıtılmış bir hesaplama çerçevesi.

Sadece pandaların içe aktarılmasını değiştirin ve kod şu şekilde çalışmalıdır:

# import pandas as pd
import ray.dataframe as pd

#use pd as usual

daha fazla ayrıntıyı burada okuyabilirsiniz:

https://rise.cs.berkeley.edu/blog/pandas-on-ray/


16

Bir varyasyon daha

Pandalarda yapılan işlemlerin çoğu bir db sorgusu olarak da yapılabilir (sql, mongo)

RDBMS veya mongodb kullanmak, DB Sorgusu'ndaki (büyük veriler için optimize edilmiş ve önbellek ve dizinleri verimli bir şekilde kullanan) toplamaların bazılarını gerçekleştirmenizi sağlar

Daha sonra pandaları kullanarak post-processing gerçekleştirebilirsiniz.

Bu yöntemin avantajı, büyük veriyle çalışmak için DB optimizasyonlarını kazanırken, aynı zamanda mantığı üst düzey bir sözdiziminde tanımlamak ve bellekte ne yapılacağına ve ne yapılacağına karar verme ayrıntılarıyla uğraşmak zorunda kalmamanızdır. Çekirdekten.

Sorgu dili ve pandalar farklı olsa da, mantığın bir kısmını birinden diğerine çevirmek genellikle karmaşık değildir.


11

Birden çok küçük dosyaya bölünmüş bir veri hattı oluşturmanın basit yoluna giderseniz Ruffus'u düşünün .


9

Geçenlerde benzer bir sorunla karşılaştım. Ben sadece parçaları veri okuma bulundu ve ben aynı csv parçalarına yazmak gibi ekleyerek iyi çalışır. Benim sorunum, aşağıdaki gibi belirli sütunların değerini kullanarak başka bir tablodaki bilgilere dayalı bir tarih sütunu eklemek oldu. Bu dask ve hdf5 ile karıştırılmış olanlara yardımcı olabilir, ancak benim gibi pandalara daha aşina olur.

def addDateColumn():
"""Adds time to the daily rainfall data. Reads the csv as chunks of 100k 
   rows at a time and outputs them, appending as needed, to a single csv. 
   Uses the column of the raster names to get the date.
"""
    df = pd.read_csv(pathlist[1]+"CHIRPS_tanz.csv", iterator=True, 
                     chunksize=100000) #read csv file as 100k chunks

    '''Do some stuff'''

    count = 1 #for indexing item in time list 
    for chunk in df: #for each 100k rows
        newtime = [] #empty list to append repeating times for different rows
        toiterate = chunk[chunk.columns[2]] #ID of raster nums to base time
        while count <= toiterate.max():
            for i in toiterate: 
                if i ==count:
                    newtime.append(newyears[count])
            count+=1
        print "Finished", str(chunknum), "chunks"
        chunk["time"] = newtime #create new column in dataframe based on time
        outname = "CHIRPS_tanz_time2.csv"
        #append each output to same csv, using no header
        chunk.to_csv(pathlist[2]+outname, mode='a', header=None, index=None)

8

Vaex paketine dikkat çekmek istiyorum.

Vaex, büyük sekmeli veri kümelerini görselleştirmek ve keşfetmek için tembel Çekirdek Dışı Veri Çerçeveleri (Pandalara benzer) için bir python kütüphanesidir. Saniyede milyar (10 9 ) nesneye / satıra kadar N boyutlu bir ızgarada ortalama, toplam, sayım, standart sapma vb. İstatistikleri hesaplayabilir . Görselleştirme histogramlar, yoğunluk grafikleri ve 3B cilt oluşturma kullanılarak yapılır ve büyük verilerin etkileşimli olarak araştırılmasını sağlar. Vaex, en iyi performans için bellek eşleme, sıfır bellek kopyalama politikası ve tembel hesaplamalar kullanır (bellek israfı olmaz).

Belgelere bir göz atın: https://vaex.readthedocs.io/en/latest/ API, pandaların API'sına çok yakın.


0

Neden Pandalar? Standart Python'u denediniz mi mi?

Standart kütüphane python kullanımı. Pandalar, kararlı sürümün son sürümünde bile sık güncellemelere tabidir.

Standart python kitaplığını kullanarak kodunuz her zaman çalışır.

Bunu yapmanın bir yolu, verilerinizin saklanma şeklini ve verilerle ilgili hangi soruları çözmek istediğinizi bilmektir. Daha sonra, normalleştirme değil, verileri sorgulamanıza yardımcı olacak verilerinizi nasıl düzenleyebileceğinize dair bir şema çizin (tabloları düşünün).

Aşağıdakilerden iyi faydalanabilirsiniz:

  • verileri bellekte saklamak için sözlüklerin listesi, bir diksiyon bir satırdır,
  • RAM'inizi aşmamak için veri satırını arka arkaya işlemek için jeneratörler,
  • verilerinizi sorgulamak için anlama listesi,
  • Counter, DefaultDict, ... kullanın
  • seçtiğiniz depolama çözümünü kullanarak verilerinizi sabit diskinizde saklayın, json bunlardan biri olabilir.

Ram ve HDD zamanla daha ucuz ve daha ucuz hale geliyor ve standart python 3 yaygın olarak mevcut ve kararlı.


-1

Şu anda sizin gibi "sadece" daha düşük bir ölçekte çalışıyorum, bu yüzden önerim için PoC'm yok.

Ancak, turşu önbellek sistemi olarak kullanma ve çeşitli işlevlerin dosyalara yürütülmesi dış kaynak kullanımı - komando / ana dosyamdan bu dosyaları yürütme başarılı buluyorum; Örneğin, nesne türlerini dönüştürmek, veri kümesini test, doğrulama ve tahmin veri kümesine bölmek için bir prepar_use.py kullanıyorum.

Turşu ile önbelleğe alma işleminiz nasıl çalışır? Hangi parametreler ve veri kümeleri geçirildiğine bağlı olarak dinamik olarak oluşturulmuş turşu dosyalarına erişmek için dizeleri kullanıyorum (bununla birlikte programın çalıştırılıp çalıştırılmadığını, veri kümesi için .shape kullanarak, geçti parametreleri). Bu önlemleri göz önünde bulundurarak, bir .pickle dosyasını bulmaya ve okumaya çalışmak için bir String alırım ve bulunursa, şu anda üzerinde çalıştığım yürütmeye atlamak için işlem süresini atlayabilir.

Veritabanlarını kullanarak benzer sorunlarla karşılaştım, bu yüzden bu çözümü kullanırken sevinç buldum, ancak - elbette birçok kısıtlama var - örneğin fazlalık nedeniyle büyük turşu setleri saklamak. Bir dönüşümden önce ve sonra bir tabloyu güncellemek uygun indeksleme ile yapılabilir - bilgilerin doğrulanması başka bir kitabı açar (taranmış kira verilerini birleştirmeyi denedim ve 2 saat sonra temelde bir veritabanı kullanmayı bıraktım - sonra geri atlamak isterdim her dönüşüm süreci)

Umarım 2 sentim size bir şekilde yardımcı olur.

Selamlar.

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.