- 事实表
- 维度表
- 模型:星型模型、雪花模型
Data lake这个术语由Pentaho公司的创始人兼首席技术官詹姆斯·狄克逊(James Dixon)提出,他对数据湖的解释是: 把你以前在磁带上拥有的东西倒入到数据湖,然后开始探索该数据。重要的只把需要的数据倒入到Hadoop;如果你想结合来自数据湖的信息和客户关系管理系统(CRM)里面的信息,我们就进行连接,只有需要时才执行这番数据结合。
数据湖是一种在系统或存储库中以自然格式存储数据的方法,它有助于以各种模式和结构形式配置数据,通常是对象块或文件。数据湖的主要思想是对企业中的所有数据进行统一存储,从原始数据(源系统数据的精确副本)转换为用于报告、可视化、分析和机器学习等各种任务的目标数据。数据湖中的数据包括
- 结构化数据(关系数据库数据)
- 半结构化数据(CSV、XML、JSON等)
- 非结构化数据(电子邮件,文档,PDF)
- 二进制数据(图像、音频、视频)
- 从而形成一个容纳所有形式数据的集中式数据存储。
- 数据集市 Data Mart
- 是满足特定的部门或者用户的需求,按照多维的方式进行存储,包括定义维度、需要计算的指标、维度的层次等,生成面向决策分析需求的数据立方体。
- 阿里提出“大中台,小前台”,中台事业部包括:
- 搜索事业部
- 共享业务平台
- 数据技术及产品部
数据技术及产品部应是数据中台建设的核心部门。
数据中台,实现数据的分层与水平解耦,沉淀公共的数据能力
- 可分为三层,数据模型、数据服务与数据开发
- 通过数据建模实现跨域数据整合和知识沉淀
- 通过数据服务实现对于数据的封装和开放,快速、灵活满足上层应用的要求
- 通过数据开发工具满足个性化数据和应用的需要
- (中国移动浙江公司傅一平)
基于数据缺失、数据待规范的数据清洗,可以被定义为侠义数据清洗
基于数据结构设计、关联关系设计、数据粒度设计的操作,这类数据清洗工作可以被定义为广义数据清洗
- select distinct fields from tablename;
- df.drop_duplicates(subset=None, keep='first', inplace=False)
- 示例:df.drop_duplicates(["Seqno"],keep="last").head()
- subset 用来指定特定的列,默认为所有列
- keep='last' 保留最后一个
- inplace=False 不改变原来的DataFrame(True时改变)
- data.drop_duplicates() # data中一行元素全部相同时才去除
- data.drop_duplicates(['a','b']) # data根据’a','b'组合列删除重复项,默认保留第一个出现的值组合。
- 去除首尾空格 select * from trim(' 空格 与 空格 ');
- 去除所有空格 select * from replace(' 空格 与 空格 ',' ','');
- 表通常具有包含唯一标识表中每一行的值的一列或一组列
- 这样的一列或多列称为表的主键 (PK),用于强制表的实体完整性
- 主键约束针对多列时,也就是组合主键约束
- 外键 (FK) 是用于在两个表中的数据之间建立和加强链接的一列或多列的组合,可控制可在外键表中存储的数据
- 一个表的主键值的一个或多个列被另一个表中的一个或多个列引用时,就在这两个表之间创建了链接
- 这个列就成为第二个表的外键
import numpy as np
import pandas as pd
# 函数eye()的作用是返回一个对角线diagonal上全是1,而其他位置全为0的一个二维数组
data = np.eye(6)
data
# np.where(condition, x, y):满足条件(condition),输出x,不满足输出y。
# np.where(condition):只有条件 (condition),没有x和y,则输出满足条件 (即非0) 元素的坐标 (等价于numpy.nonzero)。
# 这里的坐标以tuple的形式给出,通常原数组有多少维,输出的tuple中就包含几个数组,分别对应符合条件元素的各维坐标。
datanan = np.where(data,data,np.nan)
datanan
datapdnan = pd.DataFrame(datanan)
datapdnan
datapdnan.isnull()
datapdnan.isna()
datapd = datapdnan.fillna(method='ffill')
datapd
datapdnan.fillna(method='bfill')
datapd
#按行删除:存在空值,即删除该行
datapd.dropna()
#按行删除:所有数据都为空值时,即删除该行
datapd.dropna(how='all')
#按列删除:保留至少有3个非NaN值的列
datapd.dropna(axis='columns', thresh=3)
datapd
#设置子集:删除第1、2列有空值的行
datapd.dropna(axis='index', subset=[0,1,2])
#设置子集:删除第1、2、3行有空值的列
datapd.dropna(axis=1, how='any', subset=[2,3])
#原地修改原dataframe,返回值为None.
datapd.dropna(inplace=True)
datapd
df = pd.DataFrame({'name':list('ABCDA'),'house':[1,1,2,3,3],'date':['2010-01-01','2010-06-09','2011-12-03','2011-04-05','2012-03-23']})
df
# 将date列改为时间类型:
df.date = pd.to_datetime(df.date)
df
df = pd.pivot_table(df, columns='name', index='date')
df
# 用常量来替换缺失值
df.replace(np.nan,10000)
# 向下填充
df.fillna(method='ffill')
# 向上填充
df = df.fillna(method='bfill')
df
# 压缩回原来的数据结构
df.stack().reset_index()
df=pd.DataFrame(np.random.random([20,7]))
df.describe(percentiles=[.2,.3,.7,.8,.9])
#df.describe(include='all')
import matplotlib.pyplot as plt
import numpy as np
n = 50
# 随机产生50个0~2之间的x,y坐标
x = np.random.rand(n)*2
y = np.random.rand(n)*2
colors = np.random.rand(n) # 随机产生50个0~1之间的颜色值
area = np.pi * (10 * np.random.rand(n))**2 # 点的半径范围:0~10
# 画散点图
plt.scatter(x, y, s=area, c=colors, alpha=0.5, marker=('o'))
plt.show()
import pandas as pd
import numpy as np
df = pd.DataFrame({'A':['1a',np.nan,'10a','100b','0b']})
df
df.A.str.extract('(\d+)')
df = pd.DataFrame({'name':list('ABCDA'),'house':[1,1,2,3,3],'date':['2010-01-01','2010-06-09','2011-12-03','2011-04-05','2012-03-23']})
print(df.dtypes)
df.date = pd.to_datetime(df.date)
print('-'*100)
print(df.dtypes)
df
用户流失率 = 总用户流失量 / 总用户量
只有取数逻辑、清晰,才能保持指标涵义一致,才能进行对比分析
df = pd.DataFrame({'name':list('ABCDA'),'house':[1,1,2,3,3],'date':['2010-01-01','2010-06-09','2011-12-03','2011-04-05','2012-03-23']})
df
df['year']=df['date'].map(lambda x:x.split('-')[0])
df['month']=df['date'].map(lambda x:x.split('-')[1])
df['day']=df['date'].map(lambda x:x.split('-')[2])
df
a = [['01', 'a,b,c', 5], ['02','a,b', 10], ['03', 'b,c', 20]]
data = pd.DataFrame(a, index=['user1','user2','user3'], columns=["id", "type", "num"])
data
data['type'].str.split(',')
data['type'].str.split(',', expand=True)
data['type'].str.split(',', expand=True).stack()
data['type'].str.split(',', expand=True).stack().reset_index()
data_type = data['type'].str.split(',', expand=True).stack().reset_index(level = 1,drop = True)
data_type.to_frame(name='type')
data.drop(['type'], axis=1).join(data_type.to_frame( name = 'type1'))
data_new = data.drop(['type'], axis=1).join(data_type.rename('type1'))
data_new
f = 1.23456
print('%.4f' % f)
print('%.3f' % f)
print('%.2f' % f)
print(format(f, '.2f'))
print(format(f, '.3f'))
print(format(f, '.4f'))
a = 1.23456
b = 2.355
c = 3.5
d = 2.5
print(round(a, 3))
print(round(b, 2))
print(round(c))
print(round(d))
# 保留三位小数(截断,不进位)
print(int(1.23456 * 1000) / 1000 )
data_new
data_new.groupby(['id','type1'])['num'].sum().unstack()
import pandas as pd
import numpy as np
df = pd.DataFrame(np.arange(6).reshape(2,3),index=['AA','BB'],columns=['three','two','one'])
df
df.stack().to_frame()
import pandas as pd
import numpy as np
df = pd.DataFrame(np.arange(8).reshape(2,4),index=['AA','BB'],columns=[['two','two','one','one'],['A','B','C','D']])
df
df.stack()
df.stack(level=1)
df.stack(level=0)
df.stack(level=[0,1]).to_frame()
df
df.unstack().to_frame()
df = pd.DataFrame(np.arange(8).reshape(2,4),index=['AA','BB'],columns=['A','B','C','D'])
df
pd.melt(df,id_vars=['A','C'],value_vars=['B','D'],var_name='B|D',value_name='(B|D)_value')
a=[['刘玄德','男','语文',98.],['刘玄德','男','体育',60.],['关云长','男','数学',60.],['关云长','男','语文',100.]]
af=pd.DataFrame(a,columns=['name','sex','course','score'])
af
af2=af.pivot('name','course','score')
af2
af.pivot_table('score',index='name',columns='course',aggfunc='mean',margins=True,fill_value=0).reindex()
af.pivot_table('score',index='name',columns='course',aggfunc='sum',margins=True,fill_value=0).reset_index()
af.pivot_table('score',index='name',columns='course',aggfunc='sum',margins=True,fill_value=0).to_excel('test.xls')
t = pd.read_excel('test.xls')
t
import numpy as np
import pandas as pd
ages = np.array([1,2,3,4,5,10,40,36,12,58,62,77,89,100,18,20,25,30,32]) #年龄数据
ages
pd.cut(ages, 5)
for i in list(pd.cut(ages, 5)):
print(i,': ',list(pd.cut(ages, 5)).count(i))
for i in list(set(pd.cut(ages, 5))):
#print(i)
print(i.left,'->',i.right)
df1=pd.DataFrame({'key':['a','b','b'],'data1':range(3)})
print(df1)
df2=pd.DataFrame({'key':['a','b','c'],'data2':range(3)})
print(df2)
pd.merge(df1,df2,how='left')
pd.merge(df1,df2,how='right')
pd.merge(df1,df2,how='outer')
right=pd.DataFrame({'key1':['foo','foo','bar','bar'],'key2':['one','one','one','two'],'lval':[4,5,6,7]})
print(right)
left=pd.DataFrame({'key1':['foo','foo','bar'],'key2':['one','two','one'],'lval':[1,2,3]})
print(left)
pd.merge(left,right,on=['key1','key2'],how='outer')
df1=pd.DataFrame(np.random.randn(3,4),columns=['a','b','c','d'])
print(df1)
df2=pd.DataFrame(np.random.randn(2,3),columns=['b','d','a'])
print(df2)
pd.concat([df1,df2],sort=False)
pd.concat([df1,df2],sort=True,ignore_index=True)
caller = pd.DataFrame({'key':['K0', 'K1', 'K2', 'K3', 'K4', 'K5'], 'A':['A0', 'A1', 'A2', 'A3', 'A4', 'A5']})
caller
other = pd.DataFrame({'key':['K0', 'K1', 'K2','K99'], 'B':['B0', 'B1', 'B2', 'B99']})
other
caller.join(other, lsuffix='_caller', rsuffix='_other')
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib.font_manager import *
# 解决中文显示问题
# 使用场景:在text()、label()、title()中添加:fontproperties=myfont1
myfont1 = FontProperties(
fname='/usr/share/fonts/truetype/arphic/ukai.ttc'
)
# 第二种解决图例中文显示问题,配置:plt.legend(prop=myfont2)
myfont2 = matplotlib.font_manager.FontProperties(
fname='/root/anaconda3/lib/python3.7/site-packages/matplotlib/mpl-data/fonts/ttf/simhei.ttf'
, size = 16
)
# 解决不显示负号的问题
matplotlib.rcParams['axes.unicode_minus'] = False
# 解决 cannot find sans-serif family 问题
matplotlib.rcParams.update({
'font.family':'sans-serif',
'font.sans-serif':['Liberation Sans'],
})
# 有时配置后需要清除一下缓存才能正确显示
# rm -rf ~/.matplotlib/*.cache
!rm -rf ~/.matplotlib/*.cache
df = pd.read_csv('second_hand_ house.csv')
df2 = df.head(10)
df2
df3 = df2[['小区','房屋单价']].groupby('小区').mean().reset_index().sort_values(['房屋单价'],ascending=[0])
df3
data = df3['房屋单价'] # 如果该序列值合计大于1,则会归一化
labels = df3['小区']
explode =[0,0,0,0.1,0,0,0,0]
colors = ['red','pink','magenta','yellow','orange']
plt.figure(num = 1,figsize = (8,8))
# 将横、纵坐标轴标准化处理,保证饼图是一个正圆,否则为椭圆
plt.axes(aspect='equal')
# 控制X轴和Y轴的范围(用于控制饼图的圆心、半径)
plt.xlim(0,12)
plt.ylim(0,12)
#不显示边框
plt.gca().spines['right'].set_color('none')
plt.gca().spines['top'].set_color('none')
plt.gca().spines['left'].set_color('none')
plt.gca().spines['bottom'].set_color('none')
#不显示X轴、Y轴的刻度值
plt.xticks(())
plt.yticks(())
#添加图形标题
plt.title('深圳罗湖小区二手房平均单价排行榜',fontproperties=myfont2)
plt.pie(
x=data, # 绘制数据
labels=labels, # 添加编程语言标签
explode=explode, # 突出显示Python
colors=colors, # 设置自定义填充色
autopct='%.2f%%', # 设置百分比的格式,保留3位小数
pctdistance=1.4, # 设置百分比标签和圆心的距离
labeldistance=1.2, # 设置标签和圆心的距离
startangle=120, # 设置饼图的初始角度
center=(8,8), # 设置饼图的圆心(相当于X轴和Y轴的范围)
radius=1, # 设置饼图的半径(相当于X轴和Y轴的范围)
counterclock= False, # 是否为逆时针方向,False表示顺时针方向
wedgeprops= {'linewidth':1,'edgecolor':'green'}, # 设置饼图内外边界的属性值
textprops= {'fontsize':12,'color':'black','fontproperties':myfont2}, # 设置文本标签的属性值
rotatelabels = False, # 旋转每个label到指定的角度
shadow=True, # 显示阴影
frame=0 # 是否显示饼图的圆圈,1为显示
)
plt.show()
df4 = df.head(100)[['房屋单价','经度','纬度']]
df4
plt.figure(num = 1,figsize = (8,8))
plt.title('深圳罗湖小区二手房地理位置分布',fontproperties=myfont2)
plt.scatter(df4['经度'],df4['纬度'],s=df4['房屋单价']/300,c='r',alpha=0.3, linewidths=1)
plt.show()
df5 = df.head(100)[['朝向','房屋单价']].groupby('朝向').mean().reset_index().sort_values(['房屋单价'],ascending=[0])
df6 = df5.set_index('朝向')
df6
# 设置图框的大小
fig = plt.figure(figsize = (14,6))
# 绘图
plt.plot(df5['朝向'], # x轴数据
df5['房屋单价'], # y轴数据
linestyle = '-', # 折线类型
linewidth = 2, # 折线宽度
color = 'steelblue', # 折线颜色
marker = 'o', # 点的形状
markersize = 6, # 点的大小
markeredgecolor='black', # 点的边框色
markerfacecolor='brown') # 点的填充色
# 添加标题和坐标轴标签
plt.title('房屋朝向单价折线图',fontproperties=myfont2)
plt.xlabel('朝向',fontproperties=myfont2)
plt.ylabel('房屋平均单价',fontproperties=myfont2)
# 剔除图框上边界和右边界的刻度
plt.tick_params(top = 'off', right = 'off')
# 需要将df的索引设置为中文名称,然后在此处配置为刻度标签
plt.xticks(list(df5.index),list(df6.index),fontproperties=myfont2)
# 为了避免x轴日期刻度标签的重叠,可以设置x轴刻度自动展现,并且45度倾斜。但此处不倾斜
fig.autofmt_xdate(rotation = 0)
# 显示图形
plt.show()
df5
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
ax=df5.plot.bar(
x='朝向'
,y='房屋单价'
,color='orange'
,title="房屋朝向单价柱形图"
,figsize=(14,6)
,rot=360
)
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
ax=df5.sort_values(['房屋单价'],ascending=[1]).plot.barh(
x='朝向'
,y='房屋单价'
,color='orange'
,title="房屋朝向单价柱形图"
,figsize=(14,6)
,stacked = True
)
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize = (14,6))
val_ls = df5['房屋单价']
scale_ls = range(len(list(df5['朝向'])))
index_ls = df5['朝向']
plt.xticks(scale_ls,index_ls,fontproperties=myfont2)
plt.title('房屋朝向单价柱形图',fontproperties=myfont2)
plt.xlabel('朝向',fontproperties=myfont2)
plt.ylabel('房屋平均单价',fontproperties=myfont2)
plt.bar(scale_ls, val_ls,color='orange')
fig.autofmt_xdate(rotation = 0)
#plt.tight_layout()
plt.show()
df7 = df[['朝向','房屋单价']]
df7
x=np.array(list(df7['房屋单价']))
x
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize = (18,6))
x=np.array(list(df7['房屋单价']))
# 设置连续的边界值
bins=np.arange(0,100000,2500)
# 柱状图的宽度
width=2500
# 直方图会进行统计各个区间的数值
frequency_each,_,_= plt.hist(x,bins,color='red',width=width,alpha=1)
# 利用返回值来绘制区间中点连线
# 回值的bins的数据长度比频数的长度大1,
# 使用从1开始直到bins结束,即将第0个元素去掉,保证二者的长度一致,
# 再减去width的一半,保证在中点(CodeFUN)
plt.plot(bins[1:]-(width//2),frequency_each,color='red')
# 直方图会进行统计各个区间的数值
plt.hist(x,bins,color='blue',alpha=0.75)#alpha设置透明度,0为完全透明
plt.xlabel('scores')
plt.ylabel('count')
plt.grid()
plt.xlim(0,76)# 设置x轴分布范围
plt.xticks(np.arange(min(df7['房屋单价']), max(df7['房屋单价'])+6000, 3000))
plt.show()
- 房屋单价主要集中在3500元-6500元之间,其次是9000元左右
- 超过2万的房屋单价,主要集中在4.8万元-5.2万元,其次是6.5万左右
a=df7.plot.hist(
x='朝向'
,y='房屋单价'
,color='blue'
,title="房屋朝向单价折线图"
,figsize=(18,6)
,grid=True
,legend=True
,xlim=(min(df7['房屋单价'])-3000, max(df7['房屋单价'])+3000)
,xticks=np.arange(min(df7['房屋单价']), max(df7['房屋单价']), 3000)
,bins=np.arange(0,100000,2500)
)
from scipy.cluster.hierarchy import dendrogram, linkage,fcluster
from matplotlib import pyplot as plt
X = [[i] for i in [2, 8, 0, 4, 1, 9, 9, 0]]
Z = linkage(X, 'single')
f = fcluster(Z,4,'distance')
fig = plt.figure(figsize = (12,6))
dn = dendrogram(Z)
plt.show()
索引号 | 数字 |
---|---|
0 | 2 |
1 | 8 |
2 | 0 |
3 | 4 |
4 | 1 |
5 | 9 |
6 | 9 |
7 | 0 |
from pyecharts.charts import Map,Geo
from pyecharts import options as opts
data=[
("广东",10430.03)
,("山东",9579.31)
,("河南",9402.36)
,("四川",8041.82)
,("江苏",7865.99)
,("河北",7185.42)
,("湖南",6568.37)
,("安徽",5950.1)
,("浙江",5442)
,("湖北",5723.77)
,("广西",4602.66)
,("云南",4596.6)
,("江西",4456.74)
,("辽宁",4374.63)
,("黑龙江",3831.22)
,("陕西",3732.74)
,("山西",3571.21)
,("福建",3552)
,("重庆",2884)
,("贵州",3476.65)
,("吉林",2746.22)
,("甘肃",2557.53)
,("内蒙古",2470.63)
,("上海",2301.391)
,("台湾",2316.2)
,("新疆",2181.33)
,("北京",1961.2)
,("天津",1293.82)
,("海南",867.15)
,("香港",709.76)
,("青海",562.67)
,("宁夏",630.14)
,("西藏",300.21)
,("澳门",55.23)
]
map=(
Map()
.add("",data,"china")
.set_global_opts(
title_opts=opts.TitleOpts(title="各省市人口数",subtitle="数据来源:中国统计年鉴(万人)",pos_right="center",pos_top="5%"),
visualmap_opts=opts.VisualMapOpts(max_=12000),
)
)
map.render_notebook()
from pyecharts import options as opts
from pyecharts.charts import Geo
from pyecharts.globals import GeoType #Geo图的类型
data=[
("北京","2171")
,("天津","1557")
,("河北","7520")
,("内蒙古","2529")
,("辽宁","4369")
,("吉林","2717")
,("黑龙江","3789")
,("上海","2418")
,("江苏","8029")
,("浙江","5657")
,("安徽","6255")
,("福建","3911")
,("江西","4622")
,("山东","10006")
,("河南","9559")
,("湖北","5902")
,("湖南","6860")
,("广东","11169")
,("广西","4885")
,("海南","926")
,("重庆","3075")
,("四川","8302")
,("贵州","3580")
,("云南","4801")
,("西藏","337")
,("陕西","3835")
,("甘肃","2626")
,("青海","598")
,("宁夏","682")
,("新疆","2445"),
]
pop_geo = (
Geo() .add_schema(maptype="china")
.add("",data,type_=GeoType.HEATMAP) #热度效果HEATMAP
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(title_opts=opts.TitleOpts(
title="全国年度人口数"
,subtitle="数据来源:中国统计年鉴(万人)"
,pos_right="center"
,pos_top="5%"
)
,visualmap_opts=opts.VisualMapOpts(max_=11169,pos_left="8%",is_piecewise=True))
)
pop_geo.render_notebook()
from pyecharts import options as opts
from pyecharts.charts import Geo # 地理坐标系绘制方法
from pyecharts.globals import GeoType,ThemeType,SymbolType #Geo图的类型 主题 涟漪图形符号
data=[("四川","8302"),("山东","10006"),("河南","9559"),("湖南","6860"),("广东","11169")]
geo = (
Geo(init_opts=opts.InitOpts(width="600px",height="500px",theme=ThemeType.DARK))
.add_schema(maptype="china",
#itemstyle_opts=opts.ItemStyleOpts(color='white',border_color="#EE2C2C")#地图背景色
#zoom=1.5,
#is_roam=True,
#center=Geo().get_coordinate('广东'), # 视角中心
emphasis_itemstyle_opts=opts.ItemStyleOpts(color="#31708f"), # 高亮颜色
# emphasis_label_opts=opts.ItemStyleOpts(color="white", ) # 字体颜色
)
.add("",
data,
type_=GeoType.EFFECT_SCATTER,
symbol_size=6
)
.add("",
[("广东","四川"),("广东","山东"),("广东","湖南"),("广东","河南")],
type_=GeoType.LINES,
effect_opts=opts.EffectOpts(symbol=SymbolType.ARROW,symbol_size=6,color='#5f99bb'),
linestyle_opts=opts.LineStyleOpts(curve=0.2,color="#B0E2FF"))
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(title_opts=opts.TitleOpts(title="广东出发的航班",subtitle="数据来源:中国民航局官方网站",pos_right="center",pos_top="5%"))
)
geo.render_notebook()