文章目錄
- 一、資料描述
- 1、資料概覽
- 二、資料預處理
- 0、導入包和資料
- 1、列名重命名
- 2、提取資料中時間,友善後續分析繪圖
- 三、資料可視化
- 1、美國各個地區銷售額的分布(地圖)
- 2、各産品類别銷售額對比(柱狀圖)
- 3、不同客戶類别銷售額對比(餅圖)
- 4、每月各産品銷售額top10榜單
- 5、銷售額、淨利潤在時間次元的變化(折線圖)
- 6、銷售額
一、資料描述
資料集中9994條資料,橫跨1237天,銷售額為2,297,200.8603美元,利潤為286,397.0217美元,他們的庫存中有1862件獨特的物品,它們被分為3類,所有這些物品都在美國4個地區的49個州銷售,來着793位客戶的5009個訂單。
資料集: Superstore.csv 來源:kaggle
一共21列資料,每一列屬性描述如下:
Row ID => 每一行唯一的ID.
Order ID => 每個客戶的唯一訂單ID.
Order Date => 産品的訂單日期.
Ship Date => 産品發貨日期.
Ship Mode=> 客戶指定的發貨模式.
Customer ID => 辨別每個客戶的唯一ID.
Customer Name => 客戶的名稱.
Segment => The segment where the Customer belongs.
Country => 客戶居住的國家.
City => 客戶居住的城市.
State => 客戶所在的州.
Postal Code => 每個客戶的郵政編碼.
Region => “客戶”所屬地區.
Product ID => 産品的唯一ID.
Category => 所訂購産品的類别.
Sub-Category => 所訂購産品的子類别.
Product Name => 産品名稱
Sales =>産品的銷售.
Quantity => 産品數量.
Discount => 提供折扣.
Profit => 已發生的利潤/虧損.
1、資料概覽
9994行,21列資料
print(df.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 9994 entries, 0 to 9993
Data columns (total 21 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Row ID 9994 non-null int64
1 Order ID 9994 non-null object
2 Order Date 9994 non-null object
3 Ship Date 9994 non-null object
4 Ship Mode 9994 non-null object
5 Customer ID 9994 non-null object
6 Customer Name 9994 non-null object
7 Segment 9994 non-null object
8 Country 9994 non-null object
9 City 9994 non-null object
10 State 9994 non-null object
11 Postal Code 9994 non-null int64
12 Region 9994 non-null object
13 Product ID 9994 non-null object
14 Category 9994 non-null object
15 Sub-Category 9994 non-null object
16 Product Name 9994 non-null object
17 Sales 9994 non-null float64
18 Quantity 9994 non-null int64
19 Discount 9994 non-null float64
20 Profit 9994 non-null float64
dtypes: float64(3), int64(3), object(15)
memory usage: 1.6+ MB
None
二、資料預處理
0、導入包和資料
import pandas as pd
from pyecharts.charts import *
from pyecharts import options as opts
from pyecharts.commons.utils import JsCode
data = pd.read_csv(r'./data/Superstore.csv')
1、列名重命名
重命名後的列名:
data.columns = ['行ID', '訂單ID', '訂單日期', '發貨日期', '發貨方式', '客戶ID', '客戶名稱', '客戶類型', '國家', '城市', '州', '郵政編碼', '所屬區域', '産品ID',
'産品類别', '産品子類别', '産品名稱', '銷售額', '産品數量', '提供折扣', '利潤/虧損']
2、提取資料中時間,友善後續分析繪圖
data['年份'] = data['訂單日期'].apply(lambda x: x[-4:])
data['日期'] = pd.to_datetime(data['訂單日期'], format='%m/%d/%Y')
data['月份'] = data['日期'].dt.month
data['年-月'] = data['年份'].astype('str') + '-' + data['月份'].astype('str')
三、資料可視化
1、美國各個地區銷售額的分布(地圖)
包含:Order_Date Sales Quantity Profit year month
usa_sale = data[['州', '銷售額']].groupby('州').sum().round(2).reset_index()
print(usa_sale.head())
def echarts_map(province, data, title='主标題', subtitle='副标題', label='圖例'):
"""
province:傳入省份List
data:傳入各省對應的資料List
title:主标題
subtitle:副标題
label:圖例
"""
map_ = Map(
init_opts=opts.InitOpts(
bg_color='#080b30', # 設定背景顔色
theme='dark', # 設定主題
width='980px', # 設定圖的寬度
height='700px', # 設定圖的高度
)
)
map_.add(label, [list(i) for i in zip(province, data)],
maptype='美國'
)
map_.set_global_opts(
# 标題設定
title_opts=opts.TitleOpts(
title=title, # 主标題
subtitle=subtitle, # 副标題
pos_left='center', # 标題展示位置
title_textstyle_opts=dict(color='#fff') # 設定标題字型顔色
),
# 圖例設定
legend_opts=opts.LegendOpts(
is_show=True, # 是否顯示圖例
pos_left='right', # 圖例顯示位置
pos_top='3%', # 圖例距離頂部的距離
orient='horizontal' # 圖例水準布局
),
visualmap_opts=opts.VisualMapOpts(max_=int(max(data)), is_piecewise=False)
)
return map_.render(title + '-' + subtitle + '.html')
echarts_map(usa_sale['州'].tolist(), usa_sale['銷售額'].tolist(), title='美國各地區銷售額分布'
, subtitle='銷售額分布地圖', label='銷售額')

2、各産品類别銷售額對比(柱狀圖)
pro_category = data[['産品類别', '銷售額', '利潤/虧損']].groupby('産品類别').sum().round(2).reset_index()
pro_category.head()
def echarts_bar(x, y, y2, title='主标題', subtitle='副标題', label='圖例', label2='圖例2'):
"""
x: 函數傳入x軸标簽資料
y:函數傳入y軸資料
title:主标題
subtitle:副标題
label:圖例
"""
bar = Bar(
init_opts=opts.InitOpts(
bg_color='#080b30', # 設定背景顔色
theme='dark', # 設定主題
width='900px', # 設定圖的寬度
height='600px' # 設定圖的高度
)
)
bar.add_xaxis(x)
bar.add_yaxis(label, y,
label_opts=opts.LabelOpts(is_show=True) # 是否顯示資料
, category_gap="70%" # 柱子寬度設定
, yaxis_index=0
)
bar.add_yaxis(label2, y2,
label_opts=opts.LabelOpts(is_show=True) # 是否顯示資料
, category_gap="70%" # 柱子寬度設定
, yaxis_index=1
)
bar.set_series_opts( # 自定義圖表樣式
label_opts=opts.LabelOpts(
is_show=True,
position='top', # position 标簽的位置 可選 'top','left','right','bottom','inside','insideLeft','insideRight'
font_size=15,
color='white',
font_weight='bolder', # font_weight 文字字型的粗細 'normal','bold','bolder','lighter'
font_style='oblique', # font_style 文字字型的風格,可選 'normal','italic','oblique'
), # 是否顯示資料标簽
# markpoint_opts=opts.MarkPointOpts(
# data=[
# opts.MarkPointItem(type_="min", name="最小值"), # 顯示最小值标簽
# opts.MarkPointItem(type_="max", name="最大值"), # 顯示最大值标簽
# opts.MarkPointItem(type_="average", name="平均值") # 顯示均值标簽
# ]
# ),
itemstyle_opts={
"normal": {
"color": JsCode(
"""new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,color: 'rgba(0, 244, 255, 1)'}
,{offset: 1,color: 'rgba(0, 77, 167, 1)'}], false)
"""
), # 調整柱子顔色漸變
'shadowBlur': 15, # 光影大小
"barBorderRadius": [100, 100, 100, 100], # 調整柱子圓角弧度
"shadowColor": "#0EEEF9", # 調整陰影顔色
'shadowOffsetY': 2,
'shadowOffsetX': 2, # 偏移量
}
}
)
bar.set_global_opts(
# 标題設定
title_opts=opts.TitleOpts(
title=title, # 主标題
subtitle=subtitle, # 副标題
pos_left='center', # 标題展示位置
title_textstyle_opts=dict(color='#fff') # 設定标題字型顔色
),
# 圖例設定
legend_opts=opts.LegendOpts(
is_show=True, # 是否顯示圖例
pos_left='right', # 圖例顯示位置
pos_top='3%', # 圖例距離頂部的距離
orient='horizontal' # 圖例水準布局
),
tooltip_opts=opts.TooltipOpts(
is_show=True, # 是否使用提示框
trigger='axis', # 觸發類型
is_show_content=True,
trigger_on='mousemove|click', # 觸發條件,點選或者懸停均可出發
axis_pointer_type='cross', # 訓示器類型,滑鼠移動到圖表區可以檢視效果
),
yaxis_opts=opts.AxisOpts(
is_show=True,
splitline_opts=opts.SplitLineOpts(is_show=False), # 分割線
axistick_opts=opts.AxisTickOpts(is_show=False), # 刻度不顯示
axislabel_opts=opts.LabelOpts( # 坐标軸标簽配置
font_size=13, # 字型大小
font_weight='bolder' # 字重
),
), # 關閉Y軸顯示
xaxis_opts=opts.AxisOpts(
boundary_gap=True, # 兩邊不顯示間隔
axistick_opts=opts.AxisTickOpts(is_show=True), # 刻度不顯示
splitline_opts=opts.SplitLineOpts(is_show=False), # 分割線不顯示
axisline_opts=opts.AxisLineOpts(is_show=True), # 軸不顯示
axislabel_opts=opts.LabelOpts( # 坐标軸标簽配置
font_size=13, # 字型大小
font_weight='bolder' # 字重
),
),
)
bar.extend_axis(yaxis=opts.AxisOpts())
return bar.render(title + '-' + subtitle + '.html')
echarts_bar(pro_category['産品類别'].tolist(), pro_category['銷售額'].tolist(),
pro_category['利潤/虧損'].tolist(), title='不同産品類别銷售額對比', subtitle='銷售額對比柱狀圖',
label='銷售額', label2='利潤')
3、不同客戶類别銷售額對比(餅圖)
customer_sale = data[['客戶類型', '銷售額', '利潤/虧損']].groupby('客戶類型').sum().round(2).reset_index()
def echarts_pie(x, y, title='主标題', subtitle='副标題', label='圖例'):
pie = Pie(
init_opts=opts.InitOpts(
bg_color='#080b30', # 設定背景顔色
theme='dark', # 設定主題
width='900px', # 設定圖的寬度
height='600px'
)
)
pie.add('', [list(z) for z in zip(x, y)])
pie.set_series_opts(label_opts=opts.LabelOpts(
formatter="{b}: {c}",
font_size='15',
font_style='oblique',
font_weight='bolder'
)
)
pie.set_global_opts(
# 标題設定
title_opts=opts.TitleOpts(
title=title, # 主标題
subtitle=subtitle, # 副标題
pos_left='center', # 标題展示位置
title_textstyle_opts=dict(color='white'), # 設定标題字型顔色
subtitle_textstyle_opts=dict(color='white')
),
legend_opts=opts.LegendOpts(
is_show=True, # 是否顯示圖例
pos_left='right', # 圖例顯示位置
pos_top='3%', # 圖例距離頂部的距離
orient='vertical', # 圖例水準布局
textstyle_opts=opts.TextStyleOpts(
color='white', # 顔色
font_size='13', # 字型大小
font_weight='bolder', # 加粗
),
)
)
return pie.render(title + '-' + subtitle + '.html')
echarts_pie(customer_sale['客戶類型'], customer_sale['銷售額'], title='不同客戶類别銷售額對比', subtitle=' ', label='銷售額')
echarts_pie(customer_sale['客戶類型'], customer_sale['利潤/虧損'], title='不同客戶類别利潤對比', subtitle=' ', label='利潤/虧損')
4、每月各産品銷售額top10榜單
month_lis = data.sort_values(by='日期')['年-月'].unique().tolist()
month_sale = []
for i in month_lis:
month_data = data[data['年-月'] == i][['産品名稱', '銷售額']].groupby(['産品名稱']). \
sum().round(2).reset_index().sort_values(by='銷售額', ascending=False)[:10]
month_data = month_data.sort_values(by='銷售額', ascending=True)
# final_data = [month_data['産品名稱'].tolist(),month_data['銷售額'].tolist()]
month_sale.append(month_data)
# month_sale[0]
# 繪制動态榜單
# 建立一個timeline對象
def echart_line(x, y, title='主标題', subtitle='副标題', label='圖例'):
tl = Timeline(
init_opts=opts.InitOpts(
bg_color='#080b30', # 設定背景顔色
theme='dark', # 設定主題
width='1200px', # 設定圖的寬度
height='700px' # 設定圖的高度
)
)
tl.add_schema(
is_auto_play=True, # 是否自動播放
play_interval=1500, # 播放速度
is_loop_play=True, # 是否循環播放
)
for i, data1 in zip(x, y):
day = i
bar = Bar(
init_opts=opts.InitOpts(
bg_color='#080b30', # 設定背景顔色
theme='dark', # 設定主題
width='1200px', # 設定圖的寬度
height='700px' # 設定圖的高度
)
)
bar.add_xaxis(data1.iloc[:, 0].tolist())
bar.add_yaxis(
label,
data1.iloc[:, 1].round(2).tolist(),
category_gap="40%"
)
bar.reversal_axis()
bar.set_series_opts( # 自定義圖表樣式
label_opts=opts.LabelOpts(
is_show=True,
position="right",
font_style='oblique',
font_weight='bolder',
font_size='13',
), # 是否顯示資料标簽
itemstyle_opts={
"normal": {
"color": JsCode(
"""new echarts.graphic.LinearGradient(1, 0, 0, 0, [{
offset: 0,color: 'rgba(0, 244, 255, 1)'}
,{offset: 1,color: 'rgba(0, 77, 167, 1)'}], false)
"""
), # 調整柱子顔色漸變
'shadowBlur': 8, # 光影大小
"barBorderRadius": [100, 100, 100, 100], # 調整柱子圓角弧度
"shadowColor": "#0EEEF9", # 調整陰影顔色
'shadowOffsetY': 6,
'shadowOffsetX': 6, # 偏移量
}
}
)
bar.set_global_opts(
# 标題設定
title_opts=opts.TitleOpts(
title=title, # 主标題
subtitle=subtitle, # 副标題
pos_left='center', # 标題展示位置
title_textstyle_opts=dict(color='white'), # 設定标題字型顔色
subtitle_textstyle_opts=dict(color='#white')
),
legend_opts=opts.LegendOpts(
is_show=True, # 是否顯示圖例
pos_left='right', # 圖例顯示位置
pos_top='3%', # 圖例距離頂部的距離
orient='vertical', # 圖例水準布局
textstyle_opts=opts.TextStyleOpts(
color='white', # 顔色
font_size='13', # 字型大小
font_weight='bolder', # 加粗
font_style='oblique',
),
),
tooltip_opts=opts.TooltipOpts(
is_show=True, # 是否使用提示框
trigger='axis', # 觸發類型
is_show_content=True,
trigger_on='mousemove|click', # 觸發條件,點選或者懸停均可出發
axis_pointer_type='cross', # 訓示器類型,滑鼠移動到圖表區可以檢視效果
# formatter = '{a}<br>{b}:{c}人' # 文本内容
),
yaxis_opts=opts.AxisOpts(
is_show=True,
splitline_opts=opts.SplitLineOpts(is_show=False), # 分割線
axistick_opts=opts.AxisTickOpts(is_show=False), # 刻度不顯示
axislabel_opts=opts.LabelOpts( # 坐标軸标簽配置
font_size=13, # 字型大小
font_weight='bolder' # 字重
),
), # 關閉Y軸顯示
xaxis_opts=opts.AxisOpts(
boundary_gap=True, # 兩邊不顯示間隔
axistick_opts=opts.AxisTickOpts(is_show=True), # 刻度不顯示
splitline_opts=opts.SplitLineOpts(is_show=False), # 分割線不顯示
axisline_opts=opts.AxisLineOpts(is_show=True), # 軸不顯示
axislabel_opts=opts.LabelOpts( # 坐标軸标簽配置
font_size=13, # 字型大小
font_weight='bolder', # 字重
),
),
)
tl.add(bar, day)
return tl.render(title + '-' + subtitle + '.html')
# 銷售額、淨利潤在時間次元的變化(折線圖)
echart_line(month_lis, month_sale, title='每月各産品銷售額top10榜單', subtitle=' ', label='銷售額')
5、銷售額、淨利潤在時間次元的變化(折線圖)
sale_data = data.sort_values(by='日期')[['年份', '日期', '銷售額', '利潤/虧損']]. \
groupby(['年份', '日期']).sum().round(2).reset_index()
year_lis = sale_data['年份'].unique().tolist()
sale_data1 = sale_data[sale_data['年份'] == '2014']
sale_data2 = sale_data[sale_data['年份'] == '2015']
sale_data3 = sale_data[sale_data['年份'] == '2016']
sale_data4 = sale_data[sale_data['年份'] == '2017']
sale_data_lis = [sale_data1, sale_data2, sale_data3, sale_data4]
print(sale_data4.head())
def echarts_two_line(x, y, title='主标題', subtitle='副标題', label='圖例', label2='圖例2'):
"""
x: 函數傳入x軸table資料
y:函數傳入y軸dataframe集合
title:主标題
subtitle:副标題
label:圖例
"""
tab = Tab()
for table, data in zip(x, y):
line1 = Line(
init_opts=opts.InitOpts(
bg_color='#080b30', # 設定背景顔色
theme='dark', # 設定主題
width='1200px', # 設定圖的寬度
height='700px' # 設定圖的高度
)
)
line1.add_xaxis(data['日期'].tolist())
line1.extend_axis(yaxis=opts.AxisOpts()) # 添加一條Y軸
line1.add_yaxis(
label,
data['銷售額'].tolist(),
yaxis_index=0,
is_symbol_show=False, # 是否顯示資料标簽點
is_smooth=True, # 設定曲線平滑
label_opts=opts.LabelOpts(
is_show=True, # 是否顯示資料
),
# 線條粗細陰影設定
linestyle_opts={
"normal": {
"color": "#E47085", # 線條顔色
"shadowColor": '#E4708560', # 陰影顔色和不透明度
"shadowBlur": 8, # 陰影虛化大小
"shadowOffsetY": 20, # 陰影y偏移量
"shadowOffsetX": 20, # 陰影x偏移量
"width": 7 # 線條粗細
},
},
)
line1.set_global_opts(
# 标題設定
title_opts=opts.TitleOpts(
title=title, # 主标題
subtitle=subtitle, # 副标題
pos_left='center', # 标題展示位置
title_textstyle_opts=dict(color='white'), # 設定标題字型顔色
subtitle_textstyle_opts=dict(color='white')
),
# 圖例設定
legend_opts=opts.LegendOpts(
is_show=True, # 是否顯示圖例
pos_left='right', # 圖例顯示位置
pos_top='3%', # 圖例距離頂部的距離
orient='horizontal', # 圖例水準布局
textstyle_opts=opts.TextStyleOpts(
color='white', # 顔色
font_size='13', # 字型大小
font_weight='bolder', # 加粗
),
),
tooltip_opts=opts.TooltipOpts(
is_show=True, # 是否使用提示框
trigger='axis', # 觸發類型
is_show_content=True,
trigger_on='mousemove|click', # 觸發條件,點選或者懸停均可出發
axis_pointer_type='cross', # 訓示器類型,滑鼠移動到圖表區可以檢視效果
# formatter = '{a}<br>{b}:{c}人' # 文本内容
),
datazoom_opts=opts.DataZoomOpts(
range_start=0, # 開始範圍
range_end=25, # 結束範圍
# orient='vertical', # 設定為垂直布局
type_='slider', # slider形式
is_zoom_lock=False, # 鎖定區域大小
# pos_left='1%' # 設定位置
),
yaxis_opts=opts.AxisOpts(
is_show=True,
splitline_opts=opts.SplitLineOpts(is_show=False), # 分割線
axistick_opts=opts.AxisTickOpts(is_show=False), # 刻度不顯示
axislabel_opts=opts.LabelOpts( # 坐标軸标簽配置
font_size=13, # 字型大小
font_weight='bolder' # 字重
),
), # 關閉Y軸顯示
xaxis_opts=opts.AxisOpts(
boundary_gap=False, # 兩邊不顯示間隔
axistick_opts=opts.AxisTickOpts(is_show=True), # 刻度不顯示
splitline_opts=opts.SplitLineOpts(is_show=False), # 分割線不顯示
axisline_opts=opts.AxisLineOpts(is_show=True), # 軸不顯示
axislabel_opts=opts.LabelOpts( # 坐标軸标簽配置
font_size=13, # 字型大小
font_weight='bolder' # 字重
),
),
)
# 建立一個折線圖Line
line2 = Line()
line2.add_xaxis(data['日期'].tolist())
# 将line資料通過yaxis_index指向後添加的Y軸
# line2.extend_axis(yaxis=opts.AxisOpts())
line2.add_yaxis(
label2,
data['利潤/虧損'].tolist(),
yaxis_index=0,
is_symbol_show=False, # 是否顯示資料标簽點
is_smooth=True, # 設定曲線平滑
label_opts=opts.LabelOpts(
is_show=True, # 是否顯示資料
),
# 線條粗細陰影設定
linestyle_opts={
"normal": {
"color": "#44B2BE", # 線條顔色
"shadowColor": '#44B2BE60', # 陰影顔色和不透明度
"shadowBlur": 8, # 陰影虛化大小
"shadowOffsetY": 20, # 陰影y偏移量
"shadowOffsetX": 20, # 陰影x偏移量
"width": 7 # 線條粗細
},
},
)
line1.overlap(line2)
tab.add(line1, table)
return tab.render(title + '-' + subtitle + '.html')
echarts_two_line(year_lis, sale_data_lis, title='銷售額、利潤在時間次元的變化', subtitle=' ',
label='銷售額', label2='利潤/虧損')
6、銷售額
sale_sum = int(data['銷售額'].sum())
num_count = int(data['産品數量'].sum())
profit_sum = int(data['利潤/虧損'].sum())
print(profit_sum)
def big_data(title='主标題', subtitle='副标題'):
c = Pie(
init_opts=opts.InitOpts(
chart_id=1,
bg_color='#080b30',
theme='dark',
width='300px',
height='300px',
)
)
c.set_global_opts(
title_opts=opts.TitleOpts(
title=title,
subtitle=subtitle,
title_textstyle_opts=opts.TextStyleOpts(
font_size=36,
color='#FFFFFF',
),
pos_left='center',
pos_top='middle'
)
)
return c.render(str(title) + '-' + subtitle + '.html')
big_data(title=sale_sum, subtitle='銷售額')