为您提供问题的背景:
我有一个不错的SQL表(72M行,6GB),数据可以理解为"基于列的",例如:
doubleValue()
作为------------------------------
| fk_id | date | field |
------------------------------
| 1 | 2001-01-02 | 24 |
| 1 | 2001-01-03 | 25 |
| 1 | 2001-01-04 | 21 |
| 1 | 2001-01-05 | 20 |
| 1 | 2001-01-06 | 30 |
| 1 | 2001-01-07 | 33 |
| .... |
| 2 | 2001-01-02 | 10 |
| 2 | 2001-01-03 | 15 |
| 2 | 2001-01-04 | 12 |
| 2 | 2001-01-05 | 11 |
| 2 | 2001-01-06 | 10 |
| 2 | 2001-01-07 | 12 |
| .... |
| .... |
| 12455 | 2015-01-01 | 99 |
| 12456 | 2005-10-10 | 10 |
| 12456 | 2005-10-11 | 10 |
| .... |
------------------------------
的Python中所需的最终结果应该如下所示,其中pandas.DataFrame
成为索引列,列名称的外键和列date
列的值矩阵:
field
直到现在,我使用以下代码完成此操作:
------------------------------------------------------
| date | 1 | 2 | .... | 12455 | 12456 |
------------------------------------------------------
| 2001-01-02 | 24 | 10 | .... | NaN | NaN |
| 2001-01-03 | 25 | 15 | .... | NaN | NaN |
| 2001-01-04 | 21 | 12 | .... | NaN | NaN |
| 2001-01-05 | 20 | 11 | .... | NaN | NaN |
| 2001-01-06 | 30 | 10 | .... | NaN | NaN |
| 2001-01-07 | 33 | 12 | .... | NaN | NaN |
| .... | .. | .. | .... | .... | .... |
| 2005-10-10 | 50 | 4 | .... | NaN | 10 |
| 2005-10-11 | 51 | 3 | .... | NaN | 10 |
| .... | .. | .. | .... | .... | .... |
| 2015-01-01 | 40 | NaN | .... | 50 | 99 |
------------------------------------------------------
基本上做了:
def _split_by_fk(self, df):
"""
:param df: pandas.DataFrame
:param fields: Iterable
:return: pandas.Panel
"""
data = dict()
res = df.groupby('fk_id')
for r in res:
fk_id = r[0]
data[fk_id] = r[1]['field']
return pd.DataFrame(data)
def get_data(self, start, end):
s = select([daily_data.c.date, daily_data.c.fk_id, daily_data.c.field])\
.where(and_(end >= daily_data.c.date, daily_data.c.date >= start))\
.order_by(daily_data.c.fk_id, daily_data.c.date)
data = pd.read_sql(s, con=db_engine, index_col='date')
return self._split_by_fk(data)
>>> get_data('1960-01-01', '1989-12-31')
函数通过sqlalchemy查询SQL DB。pandas.read_sql
收到的groupby
DataFrame
转换为dict
。使用上述方法查询29年813列的29年日常数据4分38秒(整个DataFrame占用内存796.5MB),其中DataFrame
表示大部分时间花费在%lprun
函数中,其余在read_sql
中(输出的摘录):
_split_by_fk
我的代码感觉不是很优雅,因为我收集字典中的所有组以将它们再次转换为DataFrame。
现在我的实际问题是:是否有(更多)高效/ pythonic方式来#34;列化"以上面显示的方式% Time Line Contents
===============================================================
83.8 data = pd.read_sql(s, con=db_engine, index_col='date')
16.2 return self._split_by_fk(data)
?
PS:对于处理此类数据结构和数据量的更一般方向,我不满意,但我认为应该可以解决所有问题"小数据&#34 ;式的
答案 0 :(得分:1)
如果我理解你,你可以df.pivot(index='date', columns='fk_id', values='field')
。
我认为应该可以解决所有“小数据”风格。
祝你好运。具有12000列的DataFrame不太可能表现良好。
答案 1 :(得分:0)
如果fk_id
和date
的组合始终是唯一的,您可以执行以下操作:
df = pd.DataFrame({'fk_id': [1, 2, 3],
'date': pd.date_range('1/1/2015', periods=3),
'field': [25, 25, 1]})
# date field fk_id
# 0 2015-01-01 25 1
# 1 2015-01-02 24 2
# 2 2015-01-03 1 3
df.groupby(['date', 'fk_id']).agg(lambda x: x.unique()).unstack()
# field
# fk_id 1 2 3
# date
# 2015-01-01 25 NaN NaN
# 2015-01-02 NaN 24 NaN
# 2015-01-03 NaN NaN 1
如果它们并不总是唯一的,那么您可能需要一些更复杂的策略来聚合值。