前言
对于需要在ODPS上进行数据管理,且要用到python进行数据分析的童鞋来说,这篇总结是绝对的干货。
PyODPS提供了DataFrame的接口来处理 MaxCompute对象,也可以转换成为pandas进行数据操作。下面是数据管理中的几个常用场景:数据查询、数据写入、表删除,都是基于pandas dataframe的操作过程。
需要注意的是在dataworks中目前使用的版本是2.7,会有不少坑,譬如乱序、乱码等。
下文附代码
文中自定义函数均返回dataframe:
pyodps安装
> pip install pyodps
ODPS配置及常用包导入
from odps import ODPS
from odps import DataFrame
from odps.models import Schema, Column, Partition
import pandas as pd
from collections import defaultdict
o = ODPS('**your-access-id**', '**your-secret-access-key**', '**your-default-project**',
endpoint='**your-end-point**')
数据查询
如SDK中所述,查询表的方式有两种,一种是通过get_table方法直接获取表,另外一种是通过执行sql获取数据
get_table方法
def get_odps_table(tb_name):
data = DataFrame(o.get_table(tb_name))
data['ds'] = data['ds'].astype('int')
return data
通过sql获取数据
def exe_sql(sql):
data = []
with o.execute_sql(sql).open_reader() as reader:
d = defaultdict(list) # collection默认一个dict
for record in reader:
for res in record:
d[res[0]].append(res[1]) # 解析record中的每一个元组,存储方式为(k,v),以k作为key,存储每一列的内容;
data = pd.DataFrame.from_dict(d, orient='index').T # 转换为数据框,并转置,不转置的话是横条数据
return data
如果是在dataworks中创建的PyODPS脚本,数据会有1万条的限制,此时需要对查询数据创建临时表,再通过get_table的方式获取。上述代码做如下调整
def exe_dataworks_sql(sql):
data = []
sql_new = 'create table xisuo_tmp as %s' % (sql)
o.execute_sql(sql_new)
with o.get_table('xiatian_tmp').open_reader() as reader:
d = defaultdict(list) # collection默认一个dict
# record一行数据,res一个元组
for record in reader:
for res in record:
d[res[0]].append(res[1]) # 解析record中的每一个元组,存储方式为(k,v),以k作为key,存储每一列的内容;
data = pd.DataFrame.from_dict(d, orient='index').T # 转换为数据框,并转置,不转置的话是横条数据
o.delete_table('xisuo_tmp', if_exists=True)
if o.exist_table('xisuo_tmp'):
print('请删除临时表')
else:
print('临时表已清除')
return data
通过dataframe创建表
两种创建表的方式,一种是已知数据结构即字段、类型、备注,直接创建。
# 创建表
def create_odps_table(tb_name, schema):
try:
table = o.create_table(tb_name, schema=schema, if_not_exists=True)
return True
except:
return False
另外一种是直接通过dataframe来创建,通过程序自动对dataframe的字段进行判断,生成schema。
# 创建表
def gmt_table(tb_name, df, schema_name=None, schema_type=None, schema_comment=None):
if schema_name is None:
schema_name = df.columns.values.tolist()
if schema_type is None:
schema_type = ['string'] * len(schema_name)
if schema_comment is None:
schema_comment = [''] * len(schema_name)
df_schema = pd.DataFrame({'name': schema_name, 'type': schema_type, 'comment': schema_comment})
df_schema = df_schema[['name', 'type', 'comment']]
df_columns = df_schema.apply(lambda x: [Column(name=x[0], type=x[1], comment=x[2])], axis=1)
columns = []
for col in df_columns:
columns = columns + col
partitions = [Partition(name='ds', type='string', comment='')]
schema = Schema(columns=columns, partitions=partitions)
table = o.create_table(tb_name, schema=schema, if_not_exists=True)
return True
dataframe写入表
# 写入表
def gmt_table(tb_name, df, schema_name=None, schema_type=None, schema_comment=None):
if schema_name is None:
schema_name = df.columns.values.tolist()
if schema_type is None:
schema_type = ['string'] * len(schema_name)
if schema_comment is None:
schema_comment = [''] * len(schema_name)
df_schema = pd.DataFrame({'name': schema_name, 'type': schema_type, 'comment': schema_comment})
df_schema = df_schema[['name', 'type', 'comment']]
df_columns = df_schema.apply(lambda x: [Column(name=x[0], type=x[1], comment=x[2])], axis=1)
columns = []
for col in df_columns:
columns = columns + col
partitions = [Partition(name='ds', type='string', comment='')]
schema = Schema(columns=columns, partitions=partitions)
table = o.create_table(tb_name, schema=schema, if_not_exists=True)
return True
删除表
def drop_odps_tabel(tb_name):
table = o.delete_table(tb_name, if_exists=True)
staus = o.exist_table(tb_name)
return staus
数据集读出转换成pandas的dataframe之后,就是常规的分析过程了。
对于线上数据流的处理,后续慢慢补充。