几天前,我发布了一个关于"how to make pandas HDFStore 'put' operation faster"的问题,感谢Jeff的回答,我找到了一种从db中提取数据并将其存储到hdf5文件中的更有效方法。
但是通过这种方式,我必须根据类型填充每个单列的缺失数据,并在每个表上执行这些操作(在大多数情况下,这项工作是重复的)。否则,当我将数据帧放入hdf5文件时,数据帧中的None对象将导致性能问题。
有没有更好的方法来完成这项工作?
我刚刚读了this issue "ENH: sql to provided NaN/NaT conversions"
NaT是否可以与其他类型一起使用? (datetime64除外)
将数据帧存储到hdf5文件时,是否可以使用它替换数据帧中的所有None对象而不必担心性能问题?
更新1
pd.version:0.10.1
我正在使用np.nan来填充丢失的数据。但是我遇到了两个问题。
同时具有np.nan和datetime.datetime objs的列不能转换为“ datetime64 [ns]”类型,并且将它们放入hdfstore时会引发异常。
在[155]中:len(df_bugs.lastdiffed [df_bugs.lastdiffed.isnull()])
出[155]:150
在[156]中:len(df_bugs.lastdiffed)
出[156]:1003387
在[158]中:df_bugs.lastdiffed.astype(df_bugs.creation_ts.dtype)
-------------------------------------------------- -------------------------
ValueError跟踪(最近一次通话)
在()中
----> 1 df_bugs.lastdiffed.astype(df_bugs.creation_ts.dtype)
/ type中的/usr/local/lib/python2.6/dist-packages/pandas-0.10.1-py2.6-linux-x86_64.egg/pandas/core/series.pyc(self,dtype)
777请参阅numpy.ndarray.astype
778“”“
-> 779强制转换= com._astype_nansafe(self.values,dtype)
780 return self._constructor(casted,index = self.index,name = self.name)
781
_astype_nansafe中的/usr/local/lib/python2.6/dist-packages/pandas-0.10.1-py2.6-linux-x86_64.egg/pandas/core/common.pyc(arr,dtype)
第1047章真相大白(二更)
1048#解决NumPy破碎问题#1987
-> 1049返回lib.astype_intsafe(arr.ravel(),dtype).reshape(arr.shape)
1050
1051返回arr.astype(dtype)
pandas.lib.astype_intsafe中的/usr/local/lib/python2.6/dist-packages/pandas-0.10.1-py2.6-linux-x86_64.egg/pandas/lib.so(pandas / lib.c:11886 )()
util.set_value_at中的/usr/local/lib/python2.6/dist-packages/pandas-0.10.1-py2.6-linux-x86_64.egg/pandas/lib.so(pandas / lib.c:44436)( )
ValueError:必须是datetime.date或datetime.datetime对象
#df_bugs_sample1 = df_bugs.ix [:10000]
在[147]中:%prun store.put('df_bugs_sample1',df_bugs_sample1,table = True)
将/usr/local/lib/python2.6/dist-packages/pandas-0.10.1-py2.6-linux-x86_64.egg/pandas/io/pytables.pyc放入(自己,键,值,表,附加,** kwargs)
456桌
457“”“
-> 458 self._write_to_group(键,值,table = table,append = append,** kwargs)
459
460 def remove(self,key,where = None,start = None,stop = None):
_write_to_group中的/usr/local/lib/python2.6/dist-packages/pandas-0.10.1-py2.6-linux-x86_64.egg/pandas/io/pytables.pyc(自身,键,值,索引,表,append,complib,** kwargs)
786提高ValueError('非表不支持压缩')
787
-> 788 s.write(obj = value,append = append,complib = complib,** kwargs)
第789回
790 s.create_index(columns = index)
/usr/local/lib/python2.6/dist-packages/pandas-0.10.1-py2.6-linux-x86_64.egg/pandas/io/pytables.pyc以write(self,obj,axes,append,complib ,complevel,fletcher32,min_itemsize,chunksize,expectedrows,** kwargs)
2489#创建轴
2490 self.create_axes(axes = axes,obj = obj,validate = append,
-> 2491 min_itemsize = min_itemsize,** kwargs)
2492
2493如果不是self.is_exists:
create_axes中的/usr/local/lib/python2.6/dist-packages/pandas-0.10.1-py2.6-linux-x86_64.egg/pandas/io/pytables.pyc(self、axes、obj、validate、nan_rep ,data_columns,min_itemsize,** kwargs)
2252加薪
2253除了(Exception),细节:
-> 2254引发Exception(“找不到正确的原子类型-> [dtype->%s,items->%s]%s”%(b.dtype.name,b.items,str(detail)))
2255 j + = 1
2256
例外:找不到正确的原子类型-> [dtype-> object,items-> Index([bug_file_loc,bug_severity,bug_status,cf_branch,cf_bug_source,cf_eta,cf_public_severity,cf_public_summary,cf_regression,cf_reported_by,sys_op,sys_op,sys_type lastdiffed,优先级,rep_platform,分辨率,short_desc,status_whiteboard,target_milestone],dtype = object)]类型“ datetime.datetime”的对象没有len()
另一个df似乎无法完全放入数据帧中,如下例所示,条目数为13742515,但是在我将数据帧放入hdfstore中并取出后,条目数变为1041998.这很奇怪〜
在[123]:df_bugs_activity中
出[123]:
Int64Index:13742515条目,0到13742514
资料栏:
添加了13111366非空值
attach_id 1041998非空值
bug_id 13742515非空值
bug_when 13742515非空值
fieldid 13742515非空值
id 13742515非空值
删除了13612258非空值
谁13742515非空值
dtypes:datetime64 [ns](1),float64(1),int64(4),object(2)
在[121]中:%time store.put('df_bugs_activity2',df_bugs_activity,table = True)
CPU时间:用户35.31 s,sys:4.23 s,总计:39.54 s
挂墙时间:39.65 s
在[122]中:%time store.get('df_bugs_activity2')
CPU时间:用户7.56 s,系统:0.26 s,总计:7.82 s
壁挂时间:7.84 s
出[122]:
Int64Index:1041998个条目,2012年至13354656
资料栏:
添加1041981非空值
attach_id 1041998非空值
bug_id 1041998非空值
bug_when 1041998非空值
fieldid 1041998非空值
id 1041998非空值
删除了1041991个非空值
1041998非空值
dtypes:datetime64 [ns](1),float64(1),int64(4),object(2)
更新2
用于创建数据框的代码:
def抓取数据(表名,页面大小= 20000):
'''
从数据库表中获取数据
size_of_page:sql的limit子类的第二个参数
'''
cur.execute('从%s'%table_name中选择count(*))
records_number = cur.fetchone()[0]
循环数=记录数/页面大小+ 1
打印'**** \ n开始抓取%s \ n **** \ nrecords_number:%s \ nloop_number:%s'%(表名,记录号,循环号)
start_position = 0
df = DataFrame()#警告:此数据框对象将包含表的所有记录,因此请小心使用内存!
对于我在范围(0,loop_number)中:
sql_export ='从%s限制%s,%s'中选择*%(table_name,start_position,size_of_page)
df = df.append(psql.read_frame(sql_export,conn),verify_integrity = False,ignore_index = True)
开始位置+ =页面大小
打印'start_position:%s'%start_position
返回df
df_bugs = catch_data('bugs')
df_bugs = df_bugs.fillna(np.nan)
df_bugs = df_bugs.convert_objects()
df_bugs的结构:
Int64Index:1003387个条目,0到1003386
资料栏:
别名0非空值
signed_to 1003387非空值
bug_file_loc 498160非空值
bug_id 1003387非空值
bug_severity 1003387非空值
bug_status 1003387非空值
category_id 1003387非空值
cclist_accessible 1003387非空值
cf_attempted 102160非空值
cf_branch 691834非空值
cf_bug_source 1003387非空值
cf_build 357920非空值
cf_change 324933非空值
cf_doc_impact 1003387非空值
cf_eta 7223非空值
cf_failed 102123非空值
cf_i18n_impact 1003387非空值
cf_on_hold 1003387非空值
cf_public_severity 1003387非空值
cf_public_summary 587944非空值
cf_regression 1003387非空值
cf_reported_by 1003387非空值
cf_reviewer 1003387非空值
cf_security 1003387非空值
cf_test_id 13475非空值
cf_type 1003387非空值
cf_viss 1423非空值
component_id 1003387非空值
creation_ts 1003387非空值
截止日期0非空值
delta_ts 1003387非空值
估计的时间1003387非空值
确认1003387非空值
found_in_phase_id 1003387非空值
found_in_product_id 1003387非空值
found_in_version_id 1003387非空值
guest_op_sys 1003387非空值
host_op_sys 1003387非空值
关键字1003387非空值
lastdiffed 1003237非空值
优先级1003387非空值
product_id 1003387非空值
qa_contact 1003387非空值
剩余时间1003387非空值
rep_platform 1003387非空值
报告者1003387非空值
report_accessible 1003387非空值
分辨率1003387非空值
short_desc 1003387非空值
status_whiteboard 1003387非空值
target_milestone 1003387非空值
投票1003387非空值
dtypes:datetime64 [ns](2),float64(10),int64(19),对象(21)
更新3
写入csv并从csv中读取:
在[184]中:df_bugs.to_csv('df_bugs.sv')
在[185]中:df_bugs_from_scv = pd.read_csv('df_bugs.sv')
在[186]中:df_bugs_from_scv
出[186]:
Int64Index:1003387个条目,0到1003386
资料栏:
未命名:0 1003387非空值
别名0非空值
signed_to 1003387非空值
bug_file_loc 0非空值
bug_id 1003387非空值
bug_severity 1003387非空值
bug_status 1003387非空值
category_id 1003387非空值
cclist_accessible 1003387非空值
cf_attempted 102160非空值
cf_branch 345133非空值
cf_bug_source 1003387非空值
cf_build 357920非空值
cf_change 324933非空值
cf_doc_impact 1003387非空值
cf_eta 7223非空值
cf_failed 102123非空值
cf_i18n_impact 1003387非空值
cf_on_hold 1003387非空值
cf_public_severity 1003387非空值
cf_public_summary 588非空值
cf_regression 1003387非空值
cf_reported_by 1003387非空值
cf_reviewer 1003387非空值
cf_security 1003387非空值
cf_test_id 13475非空值
cf_type 1003387非空值
cf_viss 1423非空值
component_id 1003387非空值
creation_ts 1003387非空值
截止日期0非空值
delta_ts 1003387非空值
估计的时间1003387非空值
确认1003387非空值
found_in_phase_id 1003387非空值
found_in_product_id 1003387非空值
found_in_version_id 1003387非空值
guest_op_sys 805088非空值
host_op_sys 806344非空值
关键字532941非空值
lastdiffed 1003237非空值
优先级1003387非空值
product_id 1003387非空值
qa_contact 1003387非空值
剩余时间1003387非空值
rep_platform 424213非空值
报告者1003387非空值
report_accessible 1003387非空值
分辨率922282非空值
short_desc 1003287非空值
status_whiteboard 0非空值
target_milestone 423276非空值
投票1003387非空值
dtypes:float64(12),int64(20),对象(21)
最佳答案
我会回答自己,并感谢杰夫的帮助。
首先,更新1中的第二个问题(“似乎无法将df完全放入数据帧中”)是fixed。
而且,我遇到的最大问题是处理同时具有python的datetime obj和None obj的列。幸运的是,从0.11开始,熊猫提供了更多的convenient way。我在项目中使用了以下代码,并且为某些行添加了注释,希望它可以对其他人有所帮助:)
cur.execute('select * from table_name')
result = cur.fetchall()
# For details: http://www.python.org/dev/peps/pep-0249/#description
db_description = cur.description
columns = [col_desc[0] for col_desc in db_description]
# As the pandas' doc said, `coerce_float`: Attempt to convert values to non-string, non-numeric objects (like decimal.Decimal) to floating point
df = DataFrame(result, columns=columns, coerce_float=True)
# dealing the missing data
for column_name in df.columns:
# Currently, calling function `fillna(np.nan) on a `datetime64[ns]` column will cause an exception
if df[column_name].dtype.str != '<M8[ns]':
df[column_name].fillna(np.nan)
# convert the type of columns which both have np.nan and datetime obj from 'object' to 'datetime64[ns]'(short as'<M8[ns]')
# find the table columns whose type is Date or Datetime
column_name_type_tuple = [column[:2] for column in db_description if column[1] in (10, 12)]
# check whose type is 'object'
columns_need_conv = [column_name for column_name, column_type in column_name_type_tuple if str(df[column_name].dtype) == 'object']
# do the type converting
for column_name in columns_need_conv:
df[column_name] = Series(df[column_name].values, dtype='M8[ns]')
df = df.convert_objects()
在此之后,df应该适合存储在h5文件中,并且不再需要“拨动”。
ps:
一些资料:
complib:“ lzo”,complevel:1
表1,7,810,561条记录,其中2个整数列和1个日期时间列,推杆操作成本为49秒
table2,1,008,794记录,包含4个datetime cols,4 float64 cols,19 int cols,24 object(string)cols,放置操作花费170s