2014-09-09 2 views
10

я играл вокруг с bcolz в примерах сжатия памяти от этого notebookPython bcolz, как объединить два ctables

До сих пор я действительно поражен этой библиотекой. И я думаю, что это отличный инструмент для всех нас, которые хотят загружать большие файлы в небольшую память (хорошая работа Francesc, если вы читаете это!)

Интересно, есть ли у кого-нибудь опыт в соединении двух ctables как с пандами .merge() и как сделать это время/память эффективным.

Спасибо, что поделились своими идеями :-)!

+1

Bcolz поставляется с итераторами, поэтому, делая что-то, что не может быть просто выражено для оценки, вам нужно будет итерировать два входа. Вы хотели, чтобы весь диапазон поведения слияния, или что-то более конкретное? – mdurant

+0

@ mdurant, спасибо за ваш ответ :-). Лучше всего было бы иметь тот же функциональный диапазон, что и pd.merge. но мне уже нравится идея использования итераторов/генераторов. Я буду играть с этим и попытаться объединить его с простым MapReduce. Если я приступлю к существенным улучшениям, я опубликую здесь – PlagTag

+1

Это, лениво работающее на итераторах, может быть способ пойти - выход (также интернатор) должен быть возвращен обратно в bcolz. http://toolz.readthedocs.org/en/latest/api.html#toolz.itertoolz.join – mdurant

ответ

4

Я ПОЛУЧИЛСЯ ТОЛЬКО В ВРЕМЯ .. большое спасибо @mdurant за itertoolz !! вот какой-то псевдокод, так как пример, который я использовал, SUPER уродливый.

# here's generic pandas 
df_new = pd.merge(df1,df2) 


# example with itertoolz and bcolz 
from toolz.itertoolz import join as joinz 
import bcolz 

#convert them to ctables 
zdf1 = bcolz.ctable.fromdataframe(df1) 
zdf2 = bcolz.ctable.fromdataframe(df2) 

#column 2 of df1 and column 1 of df2 were the columns to join on 
merged = list(joinz(1,zdf1.iter(),0,zdf2.iter())) 

# where new_dtypes are the dtypes of the fields you are using 
# mine new_dtypes= '|S8,|S8,|S8,|S8,|S8' 
zdf3 = bcolz.fromiter(((a[0]+a[1]) for a in merged), dtype = new_dtypes, count = len(merged)) 

очевидно, есть, вероятно, некоторые умные способы и этот пример не очень специфичен, но он работает и может служить основанием для кого-то, чтобы построить его больше

EDIT Примеру 21 окт 7PM EST

#download movielens data files from http://grouplens.org/datasets/movielens/ 
#I'm using the 1M dataset 
import pandas as pd 
import time 
from toolz.itertoolz import join as joinz 
import bcolz 

t0 = time() 
dset = '/Path/To/Your/Data/' 
udata = os.path.join(dset, 'users.dat') 
u_cols = ['user_id', 'age', 'sex', 'occupation', 'zip_code'] 
users = pd.read_csv(udata,sep='::',names=u_cols) 

rdata = os.path.join(dset, 'ratings.dat') 
r_cols = ['user_id', 'movie_id', 'rating', 'unix_timestamp'] 
ratings = pd.read_csv(rdata, sep='::', names=r_cols) 

print ("Time for parsing the data: %.2f" % (time()-t0,)) 
#Time for parsing the data: 4.72 

t0=time() 
users_ratings = pd.merge(users,ratings) 
print ("Time for merging the data: %.2f" % (time()-t0,)) 
#Time for merging the data: 0.14 

t0=time() 
zratings = bcolz.ctable.fromdataframe(ratings) 
zusers = bcolz.ctable.fromdataframe(users) 
print ("Time for ctable conversion: %.2f" % (time()-t0,)) 
#Time for ctable conversion: 0.05 

new_dtypes = ','.join([x[0].str for x in zusers.dtype.fields.values()][::-1] +[y[0].str for y in zratings.dtype.fields.values()][::-1]) 

#Do the merge with a list stored intermediately 
t0 = time() 
merged = list(joinz(0,zusers.iter(),0,zratings.iter())) 
zuser_zrating1 = bcolz.fromiter(((a[0]+a[1]) for a in merged), dtype = new_dtypes, count = len(merged)) 
print ("Time for intermediate list bcolz merge: %.2f" % (time()-t0,)) 
#Time for intermediate list bcolz merge: 3.16 

# Do the merge ONLY using iterators to limit memory consumption 
t0 = time() 
zuser_zrating2 = bcolz.fromiter(((a[0]+a[1]) for a in joinz(0,zusers.iter(),0,zratings.iter())) , dtype = new_dtypes, count = sum(1 for _ in joinz(0,zusers.iter(),0,zratings.iter()))) 
print ("Time for 2x iters of merged bcolz: %.2f" % (time()-t0,)) 
#Time for 2x iters of merged bcolz: 3.31 

Как вы можете видеть, версия, которую я создал это 15X медленнее, чем панды, однако при использовании только итераторов это позволит сэкономить много памяти. Не стесняйтесь комментировать и/или расширяться. bcolz кажется отличным пакетом для разработки.

+0

Круто спасибо большое. – PlagTag

Смежные вопросы