数据处理与可视化

数据处理

数据预处理方法

  1. 归一化
  2. 二值化
  3. 维度变换
  4. 去重
  5. 无效数据过滤

数据处理方法

  1. 数据排序
  2. 数据查找
  3. 数据统计分析

Python 标准库之 collections

from collections import Counter

a = (0, 1, 1, 1, 2, 3, 7, 7, 23)
# 实现Counter
def count_elements(seq):
    hist = {}
    for i in seq:
        # 字典中没有i,返回默认值0
        hist[i] = hist.get(i, 0) + 1
    return hist
counted = count_elements(a)
print(counted) # {0: 1, 1: 3, 2: 1, 3: 1, 7: 2, 23: 1}
recounted = Counter(a)
print(recounted) # Counter({1: 3, 7: 2, 0: 1, 2: 1, 3: 1, 23: 1})
print(recounted.items() == counted.items()) # True

numpy

速度对比:

import time
import numpy as np

list_array = list(range(int(1e6)))
start_time = time.time()
python_array = [val*5 for val in list_array]
end_time = time.time()
print('Python array time:{}ms'.format(round((end_time-start_time)*1000,2)))

np_array = np.arange(1e6)
start_time1 = time.time()
np_array = np_array*5
end_time1 = time.time()
print('numpy array time:{}ms'.format(round((end_time1-start_time1)*1000,2)))

一些常用方法:

函数说明
abs绝对值
sqrt平方根
square平方
exp指数e^x
sign正负号:1、0、-1
ceil大于等于该元素的最小整数
floor小于等于该元素的最小整数
isnan哪些元素是非数字

一些常见的两个数组可用方法:

函数说明
add两个数组的和
subtract第一个数组减去第二个数组
mutiply两个数组元素的乘积(不是矩阵乘法)
divide第一个数组除以第二个数组
power第一个数组元素A,第二个数组元素B,A^B
fmax两个元素各个位置上更大的那个
fmin两个元素各个位置上更小的那个

一些常用的统计方法:

函数说明
sum数组所有元素的和
mean数组所有元素的平均值
std数组所有元素的标准差
min,max数组所有元素的最大或最小值
argmin,argmax数组所有元素的最小或最大值对应的位置

如何通过numpy生成序列数(sequences),重复数(repetitions)和随机数(random)

seed( ) 用于指定随机数生成时所用算法开始的整数值。

  1. 如果使用相同的seed()值,则每次生成的随即数都相同
  2. 如果不设置这个值,则系统根据时间来自己选择这个值,此时每次生成的随机数因时间差异而不同
  3. 设置的seed()值仅一次有效
# 起始位置和结束位置分别为1和50
np.linspace(start=1, stop=50, num=10, dtype=int)
# array([ 1,  6, 11, 17, 22, 28, 33, 39, 44, 50])


# 设置数组的精度为小数点后两位
np.set_printoptions(precision=2) 


a = [1,2,3] 
# 重复数组a两次
print('Tile:   ', np.tile(a, 2)) # Tile:    [1 2 3 1 2 3]
# 重复数组a每项两次
print('Repeat: ', np.repeat(a, 2)) # Repeat:  [1 1 2 2 3 3


# 生成2行2列的[0,1)的随机数
print(np.random.rand(2,2))
# 生成[0,10)的2行2列的随机整数
print(np.random.randint(0, 10, size=[2,2]))
# 生成[0,1)的2行2列的随机数
print(np.random.random(size=[2,2]))
# 从给定的列表和对应的概率分布抽样10次
print(np.random.choice(['a', 'e', 'i', 'o', 'u'], size=10, p=[0.3, .1, 0.1, 0.4, 0.1]))

Histogram

Python实线

import random
# 纯Python实现histogram
def ascii_histogram(seq):
    counted = count_elements(seq)
    for k in sorted(counted):
        print('{0:5d} {1}'.format(k, '+' * counted[k]))

random.seed(1)
vals = [1, 3, 4, 6, 8, 9, 10]
# `vals` 里面的数字将会出现5到15次
freq = (random.randint(5, 15) for _ in vals)

data = []
for f, v in zip(freq, vals):
    data.extend([v] * f)
print(ascii_histogram(data))

从数学意义上来看,直方图是分箱到频数的一种映射,它可以用来估计变量的概率密度函数的

拉普拉斯分布

import numpy as np

np.random.seed(444)
np.set_printoptions(precision=3)
d = np.random.laplace
d = np.random.laplace(loc=15, scale=3, size=500)
print(d[:5]) 
# [18.406 18.087 16.004 16.221  7.358]

# p.histogram() 默认地使用10个相同大小的区间(箱),然后返回一个元组(频数,分箱的边界)
hist, bin_edges = np.histogram(d)
print(hist)
# [ 13  23  91 261  80  21   7   2   1   1]
print(bin_edges) 
# [ 2.11   5.874  9.638 13.402 17.166 20.93  24.694 28.458 32.222 35.986  39.749]
print(hist.size, bin_edges.size)
# 10 11

Numpy到底是如何进行分箱的呢?

​ 首先获取a列表的最小值和最大值,然后设置默认的分箱数量,最后使用Numpy的 linspace方法进行数据段分割。分箱区间的结果也正好与实际吻合,0到23均等分为10份,23/10,那么每份宽度为2.3

a = (0, 1, 1, 1, 2, 3, 7, 7, 23)
# 取a的最小值和最大值
first_edge, last_edge = a.min(), a.max()
# NumPy得默认设置,10个分箱
n_equal_bins = 10
bin_edges = np.linspace(start=first_edge, stop=last_edge, num=n_equal_bins + 1, endpoint=True)
# array([ 0. ,  2.3,  4.6,  6.9,  9.2, 11.5, 13.8, 16.1, 18.4, 20.7, 23. ])

pandas

Series类型(一维)

Series API

import pandas as pd
import numpy as np
# 列表类型创建,index与列表元素个数一致
data1 = pd.Series([1,3,5,7])
# 字典类型创建,键是索引
dict_data = {
  'bj':1,
  'sh':2,
  'sz':3,
}
index_list = ['sz','bj','sh']
data2 = pd.Series(dict_data,index=index_list)
# ndarray,索引和数据都可以通过ndarray类型创建
data3 = pd.Series(np.arange(5),index=np.arange(9,4,-1))
arrays = [['Falcon', 'Falcon', 'Parrot', 'Parrot'],
           ['Captive', 'Wild', 'Captive', 'Wild']]
index = pd.MultiIndex.from_arrays(arrays, names=('Animal', 'Type'))
data4 = pd.Series([390., 350., 30., 20.], index=index, name="Max Speed")
# size返回Series数据类型
data4.groupby("Type").size()
# 重复元素出现的次数
print(data1.value_counts())
# 检测哪些数据缺失
print(data1.isnull())
print(data1.notnull())

Series类型基本操作

  1. 使用 .index 获取索引,使用 .value 获取数据
  2. Series类型的操作类似Python字典类型
    • 通过自定义索引访问
    • 保留字in操作
    • 使用get()方法
DataFrame类型(二维)

DataFrame API

pandas.DataFrame.values 返回DataFrame的Numpy形式

迭代

a=pd.DataFrame({"a":["i","j","k","i","j","k"],"b":[2,1,4,1,2,4],"c":[3,2,2,1,2,3]})
'''
	a	b	c
0	i	2	3
1	j	1	2
2	k	4	2
3	i	1	1
4	j	2	2
5	k	4	3
'''
# 迭代(列名,序列)
for i in a.items():
    print(i)
'''
('a', 0    i
1    j
2    k
3    i
4    j
5    k
Name: a, dtype: object)
('b', 0    2
1    1
2    4
3    1
4    2
5    4
Name: b, dtype: int64)
('c', 0    3
1    2
2    2
3    1
4    2
5    3
'''
Name: c, dtype: int64)
# 将行作为(索引,序列)进行迭代
for j in a.iterrows():
    print(j)
'''
(0, a    i
b    2
c    3
Name: 0, dtype: object)
(1, a    j
b    1
c    2
Name: 1, dtype: object)
(2, a    k
b    4
c    2
Name: 2, dtype: object)
(3, a    i
b    1
c    1
Name: 3, dtype: object)
(4, a    j
b    2
c    2
Name: 4, dtype: object)
(5, a    k
b    4
c    3
Name: 5, dtype: object)
'''

API

import pandas as pd
import numpy as np
# 从二维ndarray对象创建
data1 = pd.DataFrame(np.arange(10).reshape(2,5))
# 从列表类型的字典创建
dict_data = {
  'one':['xx','qq','ee','hh'],
  'two':[88,99,66,77],
  'three':['F','F','M','F'],
}
data2 = pd.DataFrame(dict_data, index=['a','b','c','d'])
# 获取第1列数据
print(data2.iloc[0])
# 删除第1列数据
del data2['one']
data2 = data2.reindex(index=['b','a','d','c'],fill_value=0)
#扔掉包含缺失的数据(NaN)的行
print(data2.dropna())
#填充所有缺失数据为一个值
print(data2.fillna(0))
# 删除索引为d的那一行数据
data2 = data2.drop('d')
# 筛选数据
print(data2[data2['two']>=90])
# 利用groupby对数据进行分组
data3 = pd.DataFrame({						
	"tag_id":["a","a","c","b","b","c"],
	"count":[10,12,20,30,10,50]
	})
# 按count 列进行降序排序 可以设置inplace=True 对原数据框应用该排序操作
print(data3.sort_values(by='count',ascending=False))
print(data3.sort_index(ascending=False, inplace=True))
data3 = data3.groupby("tag_id")
print(data3.sum())

DataFrame类型基本操作

  1. 获取某一列的值:loc根据index来索引,iloc根据行号来索引,行号从0开始,逐次加一

  2. 注意:切换得到的数据对应还是原始数据,任何修改都会反映到原始数据上

  3. 删除DataFrame中某一列数据 del

  4. .reindex()能够改变或重排Series和DataFrame索引

  5. 将缺失位置填0:fill_value=0;缺失位置通过插值法补上内容,method=ffill 从前面数据计算插值,method=bfill 从后面数据计算插值,丢弃数据dropna,填充数据fillna(0)

  6. 删除某一行数据 drop()

  7. 利用groupby对数据进行分组运算

一些常用的方法:

函数说明
count非NaN数据的数量
min、max最大、最小值
argmin、argmax最大、最小值位置
sum数值的和
mean平均数
median中位数
var方差
std标准差
describe分位数
Pandas文件读取

csv 和xls 数据读取

  • sep 用来定义分隔符
  • names 用来自定义列表
  • dtype 来定义列的类型,特别是想改变默认类型的时候 dtype={"score":int}
  • parse_dates 自动解析时间数据
  • encoding 用来解析数据使用的编码格式,主要在xls转换成csv数据时常用
    • utf-8、gb2313、gbk、gb18030
  • chunksize 当数据超出内存总量时通过设置chunksize来分段读取其中部分,chunksize用来定义一次读取的行数
import pandas as pd
# 默认把第一行当标题行读取
data = pd.read_csv('1.csv',header=None)
# 指定索引行,指定分隔符为制表符
# 通过parse_dates自动解析时间数据,[3]代表解析3号位也就是第四列数据cv
data = pd.read_csv('1.csv',names=["name",'gender','score'],index_col="name",sep="\t", parse_dates=[3])
# 存储数据为csv文件
data = pd.DataFrame({
  "key": ["a","b","c"],
  "data": [1,2,3]
})
data.to_csv('2.csv')

# 读取excel
file = pd.ExcelFile("2.xlsx")
data = file.parse("sheet1")
print(data)

json 数据读取

多层结构可以使用 json_normalize 进行进一步的解析,对于无法对应的列默认置空

import pandas as pd
from pandas.io.json import json_normalize
d = pd.read_json(r'F:\shoes1.json')
c = json_normalize(d["info"])
print(c['货号'])
字符串处理

如果数据类型不是int,(dtype: str/object),需要改变对应列类型才能求均值,具体改变方法见链接 https://www.cnblogs.com/xitingxie/p/8426340.html

# astype强制转换
data.price.astype(float).mean()
# 使用to_numeric转为数值
pd.to_numeric(data.price).mean()
  • python 原生字符串处理常用函数: len、split、replace

  • pandas Series.str 字符串处理,详见链接:https://www.cnblogs.com/P–K/p/8443995.html

    • 常用函数:split、replace、contains、extract
    • 注意:contains的结果是一个二分序列
    • expand表示是否把series类型转化为DataFrame类型
import pandas as pd
import numpy as np
import json
from pandas.io.json import json_normalize

root_path = r'F:\shoes\shoes.json'
op1 = open(root_path,encoding='utf-8')
li = []
dict1 = []
for i in op1:
  # 把字符串转换为json
  k = json.loads(i.encode('utf-8'))
  li.append(k)
# 把由json数据构成的列表转换成数据框
a = json_normalize(li)
a.isnull().sum()
# 使用to_numeric转为数值类型,常用astype
pd.to_numeric(a.price).describe()
# 去掉付款人数后面的汉字保留数字
a.sales.str.split("人",expand=True)[0].astype(int).describe()
# 过滤所有title里面有2018的商品
a[a.title.str.contains("2018")].title
# 正则表达式,抽取所有匹配到的数字
a.title.str.extract('(\d+)').head()
# 求各个省份的商品数量
p0 = a.groupby(a.location.str.split(" ",expand=True)[0]).size()
# 转换成列表
p0.tolist()
p0.index.tolist()

# 求出各个市的商品数量
a.groupby(a.location.str.split(" ",expand=True)[1]).size()
# 求出商品“info.鞋面材质”中各个特征的商品数量
a.groupby('info.鞋面材质').size()
# 求所有商品的的总付款人数(注意同样要进行类型转换)
a.sales.str.split("人",expand=True)[0].astype(int).sum()
# 选择title中包含春季的商品前五行
a[a.title.str.contains("春季")].head(5)
# 求出所有在"info.颜色分类"中有白色的商品,并求出其数量
len(a[a["info.颜色分类"].str.contains("白色")])
Pandas数据合并
  • 平均(mean),求和(sum),最大值(max),最小值(min),中位数(median),方差(var),标准差(std),累乘(prod),first,last,mean,median(中位数),mad(均值绝对偏差)
  • describe
  • size 求行数

pd.concat([a1,b1]) 纵向合并。列标对齐,不改变本身次序,行标没有改变

pd.concat([a1,b1],axis=1,join="inner") 横向合并

  • 直接抛弃置空的所在行,则需要使用join这个参数
  • 如果希望抛弃原来的索引,重建新的顺序索引的话可以用ignore_index
  • axis=1 由纵向合并变换成横向合并

r1['name'].str.split('_', expand=True) 这样返回一个DataFrame结构,如果未设置expand,返回时一个Series结构

pd.merge 基于值得数据合并

import numpy as np
import pandas as pd
a=pd.DataFrame({"a":["i","j","k","i","j","k"],"b":[2,1,4,1,2,4],"c":[3,2,2,1,2,3]})

for i in a.iterrows():
    if i[1].b+i[1].c>5:
        print(i[1])
# 推荐使用    
print(a[a.b+a.c>5])

a=np.array([[2,4],[7,1]])
b=np.array([[3,5],[2,7]])
# 将数组转换成数据框并进行横向的合并
a1=pd.DataFrame(a,index=[1,2],columns=["i","j"])
b1=pd.DataFrame(b,index=[1,2],columns=["i","j"])
pd.concat([a1,b1])

root_path = "F:\t_alibaba_data3\t_alibaba_data3.txt"
r1=pd.read_csv(root_path,names=["user","brand","behavr","date"],sep="\t",dtype={"behavr":int})
# 通过字符串的处理分离出月份序列,并把这个序列通过合并的方式作为一列并入r1
pd.concat([r1,r1.date.str.split("/",expand=True)[0]],axis=1)
r1 = r1.rename(columns = {0:"month"})
pd.DataFrame({"浏览":r1[r1.behavr==0].groupby("brand").size(),"购买":r1[r1.behavr==1].groupby("brand").size()})
r1.head()



data1 = pd.DataFrame({
		"key":["a","b","a","c","b","d"],
		"data1":[1,2,3,4,5,6]
	})
data2 = pd.DataFrame({
		"key":["a","b","c"],
		"data2":[7,8,9]
	})
#不指定连接方式  共有的才输出
print(pd.merge(data1,data2))
#有的都输出
print(pd.merge(data1,data2,how="outer"))
# 按照指定连接的列名称
print(pd.merge(data1,data2,on="key"))

pyecharts

pyecharts 是一个用于生成 Echarts 图表的类库。Echarts是百度开源的一个数据可视化 JS 库

http://pyecharts.org/

优点:

  1. 与Echarts结合
  2. 与Web端结合
  3. 超强交互性
  4. 国人开发的项目

图表绘制流程:

  1. chart_name = 图表类型() 初始化具体类型图表。
  2. chart_name.add() 添加数据及配置项
    • chart_name.add_xaxis() 添加横坐标名称
    • chart_name.add_yaxis() 添加纵坐标数据
  3. chart_name.render() 渲染生成 .html 文件

导入pyecharts模块及随机虚构数据模块

from pyecharts.faker import Faker      #创建虚构的数据
from pyecharts import options as opts  #配置
from pyecahrts.charts import Bar	   #bar图
from pyecharts.globals import ThemeType #设置主题

bar.add_xaxis(list(x)) bar.add_yaxis("name", y)

全局配置项

全局配置项可通过 get_global_options 方法设置

全局配置项

注意数据得到的是python的list/列表类型,如果是numpy的数组需要转换为list

from pyecharts.faker import Faker
from pyecharts import options as opts
from pyecharts.charts import Bar
from pyecharts.globals import ThemeType

# 实例化 柱状图/条形图
bar = Bar(init_opts=opts.InitOpts(theme=ThemeType.CHALK))
# 生成随机数据
# add_xaxis(x轴标签列表)
bar.add_xaxis(Faker.choose())
# add_yaxis(名称,y轴数据列表)
# 两两堆叠制作效果图  stack1堆2数据
bar.add_yaxis("name1", Faker.values(),stack="stack1")
bar.add_yaxis("name2",Faker.values(),stack="stack1")
				  # 标题 subtitle 副标题
bar.set_global_opts(title_opts=opts.TitleOpts(title="Bar"),
                    # 让标识偏移
                    legend_opts=opts.LegendOpts(pos_left="20%"),
                    # 旋转x轴标签
                    xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=30)),
                    # 窗口滑块
                    datazoom_opts=opts.DataZoomOpts(is_show=True),)
				  # 不显示数字
bar.set_series_opts(label_opts=opts.LabelOpts(is_show=False),
                    # 标记点
                    markpoint_opts=opts.MarkPointOpts(
                      data=[
                        opts.MarkPointItem(type_="max", name="最大值"),
                        opts.MarkPointItem(type_="min", name="最小值"),
                      ]
                    ),
                    # 标记线
                    markline_opts=opts.MarkLineOpts(
                      data=[
                          opts.MarkLineItem(type_="average", name="平均值"),
                      ]
                    ))
bar.render_notebook()
系列配置项

系列配置项可通过 set_series_opts 方法设置

练习:

from pyecharts import options as opts
from pyecharts.charts import Bar
from pyecharts.globals import ThemeType

x=range(1,8)
y=[114, 55, 27, 101, 125, 27, 105]

bar = Bar(init_opts=opts.InitOpts(theme=ThemeType.ESSOS))
bar.add_xaxis(list(x))
bar.add_yaxis("name",y)
# 翻转 XY 轴数据
bar.reversal_axis()
bar.set_series_opts(label_opts=opts.LabelOpts(font_style="italic",font_size=20),
                   markline_opts=opts.MarkLineOpts(
                    data=[
                        opts.MarkLineItem(type_="max", name="最大值"),
                        opts.MarkLineItem(type_="min", name="最小值"),
                        opts.MarkLineItem(type_="average", name="平均值"),
                    ]
                   ))
bar.set_global_opts(yaxis_opts=opts.AxisOpts(max_=135))
bar.render_notebook()
pyecharts数据类型问题

https://pyecharts.org/#/zh-cn/data_format

由于pyecharts背后封装的js库,会涉及到数据类型转换。它暂时需要输入数据必须是python的基础数据类型,比如字符串,列表,字典,而不能是序列这样的数据类型,因此序列输入量需要事先呗转化为list等基础数据类型才能被pyecharts支持

pandas数据类型转换成python数据类型 tolist()

zip(a,b)zip()函数分别从a和b依次各取出一个元素组成元组,再将依次组成的元组组合成一个新的迭代器–新的zip类型数据

图标类型

基本图表

直角坐标系图表

组合图表

3D图表

多维数据可视化1

import json
import pandas as pd
from pandas.io.json import json_normalize
op1 = open(r'D:\shoes\shoes.json','r',encoding='utf-8')
li = []
dict1 = {}
for i in op1:
    k = json.loads(i.encode('utf-8'))
    li.append(k)
a = json_normalize(li)

a.groupby("nick").size().sort_values(ascending=False)
#计算上面排名前二的两个商家各个款式的对应的商品数量,并且组成矩阵,使得第一列是"意尔康皮鞋旗舰店"对应的商品数量,第二列是"米兰多格商场"的
t1 = a[a.nick=="意尔康皮鞋旗舰店"].groupby("info.款式").size()
t2 = a[a.nick=="米兰多格商场"].groupby("info.款式").size()
p0 = pd.concat([t1,t2], axis=1,sort=False).fillna(0)

from pyecharts import options as opts
from pyecharts.globals import ThemeType
from pyecharts.charts import Bar, Grid, Line, Scatter, Tab, Timeline
from pyecharts.charts import Page, Pie, Funnel

# 直角坐标系
# f1 = Line(init_opts=opts.InitOpts(theme=ThemeType.ESSOS)).add_xaxis(p0.index.tolist()).add_yaxis("name",p0.tolist())
# f1.set_global_opts(title_opts = opts.TitleOpts(title="意尔康男鞋分析"))
# f1.render_notebook()

# 饼图
# f2=Pie().add("", [list(z) for z in zip(p0.index.tolist(), p0.tolist())])
# f2.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
# f2.set_global_opts(
#             title_opts=opts.TitleOpts(title="意尔康男鞋分析"),
#             legend_opts=opts.LegendOpts(
#                 orient="vertical", pos_top="15%", pos_left="2%"
#             ),
#         )
# f2.render_notebook()

# 漏斗图
# f3 = Funnel().add("", [list(z) for z in zip(p0.index.tolist(), p0.tolist())],
#                  sort_ = 'ascending',
#                  label_opts=opts.LabelOpts(position="inside"))
# f3.set_global_opts(title_opts=opts.TitleOpts(title="意尔康男鞋分析"),
#                    legend_opts=opts.LegendOpts(
#                        orient="vertical", pos_top="15%", pos_left="2%"
#                    ),
#                   )
# f3.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
# f3.render_notebook()

########################################

# 组合图表
f1 = Bar(init_opts=opts.InitOpts(theme=ThemeType.PURPLE_PASSION))
f1.add_xaxis(p0.index.tolist())
f1.add_yaxis("意尔康皮鞋旗舰店",p0[0].tolist())
f1.set_global_opts(title_opts=opts.TitleOpts(title="Grid"),legend_opts=opts.LegendOpts(pos_left="20%"))

f2 = Line(init_opts=opts.InitOpts(theme=ThemeType.PURPLE_PASSION))
f2.add_xaxis(p0.index.tolist())
f2.add_yaxis("米兰多格商场",p0[1].tolist())
f2.set_global_opts(title_opts=opts.TitleOpts(title="Grid"))
# 并行多图
# g1 = Grid(init_opts=opts.InitOpts(theme=ThemeType.PURPLE_PASSION))
# g1.add(f1,grid_opts=opts.GridOpts(pos_left="55%"))
# g1.add(f2,grid_opts=opts.GridOpts(pos_right="55%"))
# 组合图表
# tab1 = Tab()
# tab1.add(f1, "意尔康皮鞋旗舰店")
# tab1.add(f2, "米兰多格商场")
# 时间轮播图
t1 = Timeline()
t1.add(f1, "意尔康皮鞋旗舰店")
t1.add(f2, "米兰多格商场")
t1.render_notebook()

多维数据可视化2

import json
import pandas as pd
from pandas.io.json import json_normalize
op1 = open(r'D:\shoes\shoes.json','r',encoding='utf-8')
li = []
dict1 = {}
for i in op1:
    k = json.loads(i.encode('utf-8'))
    li.append(k)
a = json_normalize(li)

p0 =a.groupby(["info.鞋面材质","info.风格"]).size().sort_values(ascending=False)

from pyecharts import options as opts
from pyecharts.charts import Bar3D, HeatMap
x = []
y = []
data = []
for i in p0.iteritems():
    if i[0][0] not in x:
        x.append(i[0][0])
    if i[0][1] not in y:
        y.append(i[0][1])
    data.append([x.index(i[0][0]),y.index(i[0][1]),i[1]])
# 3D柱状图
# f1 = Bar3D()
# f1.add("",data,
#       xaxis3d_opts=opts.Axis3DOpts(x, type_="category"),
#       yaxis3d_opts=opts.Axis3DOpts(y, type_="category"),
#       zaxis3d_opts=opts.Axis3DOpts(type_="value"),)
# f1.set_global_opts(visualmap_opts=opts.VisualMapOpts(max_=20),
#                   title_opts=opts.TitleOpts(title="Bar3D-基本示例"))
# 热图
f2 = HeatMap()
f2.add_xaxis(x)
f2.add_yaxis("series", y, data)
f2.set_global_opts(title_opts=opts.TitleOpts(title="HeatMap-基本示例"),
                  visualmap_opts=opts.VisualMapOpts(),)
f2.render_notebook()

多维数据可视化3

import json
import pandas as pd
from pandas.io.json import json_normalize
import numpy as np
op1 = open(r'D:\shoes\shoes.json','r',encoding='utf-8')
li = []
dict1 = {}
for i in op1:
    k = json.loads(i.encode('utf-8'))
    li.append(k)
a = json_normalize(li)

a.sales = a.sales.str.split('人', expand=True)[0]
a.sales = a_sales.astype(np.int64)
a.price = a.price.astype(np.float)
z1 = a.sales*a.price
z1.name = "xse"
a1 = pd.concat([a,z1],axis=1)
# a1.head(2)
# 先做成字典,把各个特征放入字典中
te_zheng = {"nick":[],"z_xse":[],"z_num":[],"p_sales":[],"p_bdj":[],"p_price":[]}
for i in a1.groupby("nick"):
    te_zheng["nick"].append(i[0])
    te_zheng["z_xse"].append(i[1].xse.sum())
    te_zheng["z_num"].append(len(i[1]))
    # 求平均值
    te_zheng["p_sales"].append(round(i[1].sales.mean(),1))
    # 笔单价 存在除零的情况,所以做判断
    if i[1].sales.sum() == 0:
        te_zheng["p_bdj"].append(0)
    else:
        te_zheng["p_bdj"].append(round(i[1].xse.sum()/i[1].sales.sum(),1))
    te_zheng["p_price"].append(round(i[1].price.mean(),1))
    
from pyecharts.charts import Scatter
from pyecharts.charts import Page, Parallel
# f1=Scatter(init_opts=opts.InitOpts(theme=ThemeType.PURPLE_PASSION))
# f1.add_xaxis(df_te_zheng[0:20].z_xse.tolist())
# f1.add_yaxis("商家A",df_te_zheng[0:20].p_bdj.tolist())
# 注意pyechart的x轴通常默认为类别轴,需要重新设定为数值轴
# 类别轴只管字符串排序 不管其位置
# f1.set_global_opts(xaxis_opts=opts.AxisOpts(type_='value'),datazoom_opts=opts.DataZoomOpts(is_show=True))
# f1.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
# f1.render_notebook()

z1 = df_te_zheng.head(5)
data1=[]
for i in z1.iterrows():
    data1.append(i[1].tolist()[1:])
    
f2 = Parallel().add_schema(
    [
        # 注意这里的序号对应于data1中列表的索引
        {"dim":0, "name":"z_xse"},
        {"dim":1, "name":"z_num"},
        {"dim":2, "name":"p_sales"},
        {"dim":3, "name":"p_bdj"},
        {"dim":4, "name":"p_price"},        
    ]
)
f2.add("parallel", data1)
f2.set_global_opts(title_opts=opts.TitleOpts(title="Parallel-基本示例"))
f2.render_notebook()
统计分布与数据可视化

value_counts(bin=500) bin是指在最小值和最大值之间选择500个区间,然后统计在各个区间内的商品数量,pandas.Interval 类型(区间),是闭合的,区间可以求中值(mid)

import numpy as np
import pandas as pd
import json
from pandas.io.json import json_normalize
from collections import Counter

op1=open(r'D:\数据分析与可视化数据\shoes\shoes.json', 'r',encoding='utf-8')
li=[]
dict1={}
for i in op1:
    k = json.loads(i.encode("utf-8"))
    li.append(k)
a = json_normalize(li)

a.sales = a.sales.str.split("人",expand=True)[0]
a.sales = a.sales.astype(np.int64)
a.price = a.price.astype(np.float)
p1 = a.price.value_counts()
# 这里没有按照值大小进行排序,如果排序会破坏曲线的状态
p2 = a.sales.value_counts(bins=500,sort=False)
x=[]
y=[]
for i in p2.items():
    x.append(i[0].mid)
    y.append(i[1])

from pyecharts.globals import ThemeType
from pyecharts import options as opts
from pyecharts.charts import Line
# is_smooth 是否平滑曲线
f1 = Line().add_xaxis(x).add_yaxis("price", y, is_smooth=True)
f1.set_global_opts(title_opts=opts.TitleOpts(title="意尔康男鞋分析"),
                   xaxis_opts=opts.AxisOpts(type_="value"),
                  datazoom_opts=opts.DataZoomOpts(is_show=True))
f1.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
# 淘宝商品价格分布的双峰特征明显
f1.render_notebook()

基于histogram进行含权统计

  • 假如我们不仅想知道某个区间的商品数量,并且还想知道在此区间商品的销售情况,这样就需要引入销量作为权值进行含权统计
  • histogram能统计区间的数量,并且更强大的在于能够进行含权统计
import numpy as np
import pandas as pd
import json
from pandas.io.json import json_normalize
from collections import Counter

op1=open(r'D:\数据分析与可视化数据\shoes\shoes.json', 'r',encoding='utf-8')
li=[]
dict1={}
for i in op1:
    k = json.loads(i.encode("utf-8"))
    li.append(k)
a = json_normalize(li)

a.sales = a.sales.str.split("人",expand=True)[0]
a.sales = a.sales.astype(np.int64)
a.price = a.price.astype(np.float)
p1 = a.price.value_counts()
# 这里没有按照值大小进行排序,如果排序会破坏曲线的状态
p2 = a.sales.value_counts(bins=500,sort=False)
# 求"info.鞋面材质"为"头层牛皮(除牛反绒)"的商品的价格分布
x2 = []
y2 = []
for i in p2.items():
    x2.append(i[0].mid)
    y2.append(i[1])
s1 = a[a["info.鞋面材质"]=="头层牛皮(除牛反绒)"].price.value_counts(bins=400).sort_index()
x1 = []
y1 = []
for i in s1.items():
    x1.append(i[0].mid)
    y1.append(i[1])

# 求各个店铺的商品数量分布图
# n1 = a.groupby("nick").size().value_counts().sort_index()
# y = n1.tolist()
# x = n1.index.tolist()

y,x = np.histogram(a.price.values,np.linspace(a.price.min(),700,50),weights=a.sales.values)
# 由于上面区间值比区间要多一个数,为了对应在区间量里增加了一个值,以满足对应要求
f1=Line().add_xaxis(x.tolist()).add_yaxis("price", [0]+y.tolist(),is_smooth=True)
f1.set_global_opts(title_opts=opts.TitleOpts(title="意尔康男鞋分析"),
                   xaxis_opts=opts.AxisOpts(type_="value"),
                  datazoom_opts=opts.DataZoomOpts(is_show=True))
f1.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
# 200左右极大值相比300左右极大值区间,前者商品数量多但是后者在商品数量少的情况下一点不逊色,说明300左右的竞争力小很多
f1.render_notebook()

通过箱型图来可视化了解分位数情况

  • apply作为一种基于数据框的函数的遍历方法,能把函数自动作用到groupby的每一个组
import json
import pandas as pd
from pandas.io.json import json_normalize

op1=open(r'D:\数据分析与可视化数据\shoes\shoes.json', 'r',encoding='utf-8')
li=[]
dict1={}
for i in op1:
    k = json.loads(i.encode("utf-8"))
    li.append(k)
a = json_normalize(li)

a.groupby("info.鞋面材质").size()
def c1(x):
    return x.price.values
p3 = a.groupby("info.鞋面材质").apply(c1)

from pyecharts.charts import Boxplot
x=["PU","二层牛皮(除牛反绒)","头层牛皮(除牛反绒)","人造革"]
y=[p3[x[0]],p3[x[1]],p3[x[2]],p3[x[3]]]
c = Boxplot()
c.add_xaxis(x).add_yaxis("A", c.prepare_data(y))
c.set_global_opts(title_opts=opts.TitleOpts(title="BoxPlot-基本示例"))
c.render_notebook()
#头层牛皮最贵
#材质越差,价格波动空间越小,好材质,定价空间更大
时间数据可视化

date类是一个时间类,由年、月、日组成。

类的构造函数如下:class datetime.date(year, month, day)

给日期加一个时间间隔(datetime.timedelta类的对象)

date.fromtimestamp()函数:根据给定的时间戳,返回一个date对象

import datetime
import randint
import time

now = datetime.date.today()
a = datetime.timedelta(days=10)
b = now+b

now = time.time()
s = datetime.date.fromtimestamp(now)

begin = datetime.date(2017, 1, 1)
end = datetime.date(2017, 12, 31)
data = [
    [str(begin + datetime.timedelta(days=i)), random.randint(1000, 25000)]
    for i in range((end - begin).days + 1)
]

数据结构:[str(begin + datetime.timedelta(days=i)), random.randint(1000, 25000)] for i in range((end - begin).days + 1)

import pandas as pd
r1 = pd.read_csv(r"D:\数据分析与可视化数据\t_alibaba_data3\t_alibaba_data3.txt",names=["user","brand","behavr","date"],sep="\t",dtype={"behavr":int})
r1.date = "2011/" + r1.date
r1.date = pd.to_datetime(r1.date)
t1 = r1.groupby(pd.Grouper(key="date")).size()
t1.sort_index(inplace=True)

from pyecharts.charts import Line
f1=Line().add_xaxis(t1.index.tolist()).add_yaxis("price", t1.tolist(),is_smooth=True)
f1.set_global_opts(title_opts=opts.TitleOpts(title="意尔康男鞋分析"),
                   xaxis_opts=opts.AxisOpts(type_="time"))
f1.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
f1.render_notebook()

from pyecharts import options as opts
from pyecharts.charts import Calendar
c1 = Calendar()
c1.add("", data, calendar_opts=opts.CalendarOpts(range_=["2011-04-15","2011-08-15"]))
c1.set_global_opts(
            title_opts=opts.TitleOpts(title="Calendar-2011年品牌销售量"),
            visualmap_opts=opts.VisualMapOpts(
                max_=3000,
                min_=40,
                orient="horizontal",
                # 是否为分段型
                is_piecewise=True,
                pos_top="230px",
                pos_left="100px",
            ),
        )
c1.render_notebook()
pyecharts基于page的布局
from pyecharts.globals import ThemeType
from pyecharts.faker import Faker
from pyecharts import options as opts
from pyecharts.charts import Bar, Grid, Line, Page, Pie

bar1 = Bar(init_opts=opts.InitOpts(theme=ThemeType.PURPLE_PASSION))
bar1.add_xaxis(['comments_count','reposts_count','attitudes_count'])
bar1.add_yaxis("韩寒", [1265,495,3931])
bar1.add_yaxis("蔡徐坤", [42,159,202])
bar1.set_global_opts(title_opts=opts.TitleOpts(title="转发反馈统计"),toolbox_opts=opts.ToolboxOpts())

bar2 = Bar(init_opts=opts.InitOpts(theme=ThemeType.PURPLE_PASSION))
bar2.add_xaxis(['repost'])
bar2.add_yaxis("韩寒", [32585])
bar2.add_yaxis("蔡徐坤", [22630])
bar2.set_global_opts(title_opts=opts.TitleOpts(title="某商场销售情况"),toolbox_opts=opts.ToolboxOpts())

page = Page(layout=Page.DraggablePageLayout)
# 需要自行调整每个 chart 的 height/width,显示效果在不同的显示器上可能不同
page.add(bar1,bar2)
page.render()
#运行上面代码后会在下面的目录中出现一个render.html文件,文件里包含上面两张图,打开此html文件,可以拖动图形到你想要的位置
#拖动完成后点击左上角的save config,然后会在你的浏览器下载目录里生成一个“chart_config.json”文件
#如果目录下已经有了此文件会生成的是chart_config (1),注意再windows系统下建议把chart_config (1)中的空格去掉,这样的文件名才符合规范
page.save_resize_html("render.html", cfg_file=r"C:\Users\Downloads\chart_config3.json", dest="my_new_charts.html")
#拖动完成后再下面输出上面命令,运行则会生成按照你的要求布局的可视化html文件
地图与地理坐标可视化

Geo - Geo_base

数据结构:[list(z) for z in zip(Faker.provinces, Faker.values())]

经纬度查询:https://www.toolnb.com/tools/getbaidupoint.html

import numpy as np
import pandas as pd
import json
from pandas.io.json import json_normalize
import pyecharts as pe
from collections import Counter

# 官网的案例
from pyecharts.faker import Faker
from pyecharts import options as opts
from pyecharts.charts import Geo
from pyecharts.globals import ChartType, SymbolType

g0 = Geo()
g0.add_schema(maptype="浙江")#可以通过maptype来选择具体省市的地图
g0.add("geo", [["杭州",50],["宁波",30],["义乌",20],["萧山",99]])
g0.set_series_opts(label_opts=opts.LabelOpts(is_show=False))#去掉标识
g0.set_global_opts(
            visualmap_opts=opts.VisualMapOpts(is_piecewise=True,max_=300),
            title_opts=opts.TitleOpts(title="Geo-基本示例"),
        )
g0.render_notebook()


from pyecharts.globals import GeoType
city = '杭州'
g = Geo()
g.add_schema(maptype=city)
# 定义坐标对应的名称,添加到坐标库中 add_coordinate(name, lng, lat)
g.add_coordinate('杭州师范大学仓前校区',120.0109472358, 30.2910373720)#注意这里要求经度在前维度在后
g.add_coordinate('萧山城厢街道',120.2740081170, 30.1605364542)
# 定义数据对
data_pair = [('杭州师范大学仓前校区', 10),('萧山城厢街道', 5),("杭州",50)]

# Geo 图类型,有 scatter, effectScatter, heatmap, lines 4 种,建议使用
# from pyecharts.globals import GeoType
# GeoType.GeoType.EFFECT_SCATTER,GeoType.HEATMAP,GeoType.LINES
# 将数据添加到地图上
g.add('', data_pair, type_=GeoType.EFFECT_SCATTER, symbol_size=15)
# 设置样式
g.set_series_opts(label_opts=opts.LabelOpts(is_show=False))

# 自定义分段 color 可以用取色器取色
pieces = [
        {'max': 6, 'label': '5以下', 'color': '#FF00FF'},
        {'min': 6, 'max': 10, 'label': '5-10', 'color': 'yellow'},
        {'min': 10, 'max': 100, 'label': '10-100', 'color': 'red'} # 有下限无上限
    ]
#  is_piecewise 是否自定义分段, 变为true 才能生效
g.set_global_opts(
        visualmap_opts=opts.VisualMapOpts(is_piecewise=True, pieces=pieces),#注意默认max_
        title_opts=opts.TitleOpts(title="{}-店铺分布".format(city)),
    )

g.render_notebook()
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值