Saya secara rutin menggunakan puluhan gigabyte data hanya dalam mode ini. Saya memiliki tabel di disk yang saya baca melalui kueri, membuat data, dan menambahkan kembali.
Sebaiknya baca dokumen dan di akhir utas ini untuk mendapatkan beberapa saran tentang cara menyimpan data Anda.
Detail yang akan memengaruhi cara Anda menyimpan data, seperti:
Berikan detail sebanyak mungkin; dan saya dapat membantu Anda mengembangkan struktur.
- Ukuran data, # baris, kolom, jenis kolom; apakah Anda menambahkan baris, atau hanya kolom?
- Seperti apa operasi tipikal itu. Misalnya. lakukan kueri pada kolom untuk memilih sekelompok baris dan kolom tertentu, lalu lakukan operasi (dalam memori), buat kolom baru, simpan ini.
(Memberikan contoh mainan dapat memungkinkan kami menawarkan rekomendasi yang lebih spesifik. ) - Setelah proses itu, lalu apa yang Anda lakukan? Apakah langkah 2 ad hoc, atau dapat diulang?
- Masukkan file datar:berapa banyak, ukuran total kasar dalam Gb. Bagaimana ini diatur mis. oleh catatan? Apakah masing-masing berisi bidang yang berbeda, atau apakah mereka memiliki beberapa catatan per file dengan semua bidang di setiap file?
- Apakah Anda pernah memilih subset baris (rekaman) berdasarkan kriteria (misalnya, memilih baris dengan bidang A> 5)? dan kemudian melakukan sesuatu, atau Anda hanya memilih bidang A, B, C dengan semua catatan (lalu melakukan sesuatu)?
- Apakah Anda 'mengerjakan' semua kolom Anda (dalam kelompok), atau apakah ada proporsi yang baik yang hanya dapat Anda gunakan untuk laporan (mis. Anda ingin menyimpan data, tetapi tidak perlu menariknya eksplisit kolom sampai waktu hasil akhir)?
Solusi
Pastikan Anda memiliki panda setidaknya 0.10.1
terpasang.
Baca file iterasi sepotong demi sepotong dan beberapa kueri tabel.
Karena pytables dioptimalkan untuk beroperasi berdasarkan baris (yang Anda kueri), kami akan membuat tabel untuk setiap grup bidang. Dengan cara ini mudah untuk memilih sekelompok kecil bidang (yang akan berfungsi dengan tabel besar, tetapi lebih efisien untuk melakukannya dengan cara ini ... Saya pikir saya mungkin dapat memperbaiki batasan ini di masa mendatang ... ini lebih intuitif bagaimanapun):
(Berikut ini adalah pseudocode.)
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'] ]))
Membaca dalam file dan membuat penyimpanan (pada dasarnya melakukan apa yang append_to_multiple
tidak):
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'])
Sekarang Anda memiliki semua tabel dalam file (sebenarnya Anda dapat menyimpannya dalam file terpisah jika diinginkan, Anda mungkin harus menambahkan nama file ke group_map, tetapi mungkin ini tidak perlu).
Beginilah cara Anda mendapatkan kolom dan membuat yang baru:
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)
Saat Anda siap untuk post_processing:
# 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)
Tentang kolom_data, Anda sebenarnya tidak perlu mendefinisikan APAPUN data_kolom; mereka memungkinkan Anda untuk memilih baris berdasarkan kolom. Misalnya. sesuatu seperti:
store.select(group, where = ['field_1000=foo', 'field_1001>0'])
Mereka mungkin paling menarik bagi Anda dalam tahap pembuatan laporan akhir (pada dasarnya kolom data dipisahkan dari kolom lain, yang mungkin sedikit memengaruhi efisiensi jika Anda mendefinisikan banyak).
Anda juga mungkin ingin:
- buat fungsi yang mengambil daftar bidang, mencari grup di groups_map, lalu memilih ini dan menggabungkan hasilnya sehingga Anda mendapatkan bingkai yang dihasilkan (ini pada dasarnya adalah apa yang dilakukan select_as_multiple). Dengan cara ini strukturnya akan cukup transparan bagi Anda.
- indeks pada kolom data tertentu (membuat sub-pengaturan baris lebih cepat).
- aktifkan kompresi.
Beri tahu saya jika ada pertanyaan!