mdbq 3.3.13__py3-none-any.whl → 3.3.15__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mdbq/aggregation/datashow.py +606 -0
- mdbq/aggregation/query_data.py +6 -1
- mdbq/spider/aikucun.py +1 -1
- {mdbq-3.3.13.dist-info → mdbq-3.3.15.dist-info}/METADATA +1 -1
- {mdbq-3.3.13.dist-info → mdbq-3.3.15.dist-info}/RECORD +7 -6
- {mdbq-3.3.13.dist-info → mdbq-3.3.15.dist-info}/WHEEL +0 -0
- {mdbq-3.3.13.dist-info → mdbq-3.3.15.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,606 @@
|
|
1
|
+
# -*- coding: UTF-8 –*-
|
2
|
+
import os
|
3
|
+
import socket
|
4
|
+
import platform
|
5
|
+
import datetime
|
6
|
+
import time
|
7
|
+
from mdbq.config import myconfig
|
8
|
+
from mdbq.mysql import mysql
|
9
|
+
from mdbq.mysql import s_query
|
10
|
+
import pandas as pd
|
11
|
+
import numpy as np
|
12
|
+
import plotly.express as px
|
13
|
+
import plotly.graph_objects as go
|
14
|
+
from plotly.subplots import make_subplots
|
15
|
+
import tkinter as tk
|
16
|
+
|
17
|
+
from sqlalchemy.sql.functions import count
|
18
|
+
|
19
|
+
m_engine = mysql.MysqlUpload(username='', password='', host='', port=0, charset='utf8mb4')
|
20
|
+
company_engine = mysql.MysqlUpload(username='', password='', host='', port=0, charset='utf8mb4')
|
21
|
+
|
22
|
+
if socket.gethostname() == 'company' or socket.gethostname() == 'Mac2.local':
|
23
|
+
conf = myconfig.main()
|
24
|
+
conf_data = conf['Windows']['xigua_lx']['mysql']['remoto']
|
25
|
+
username, password, host, port = conf_data['username'], conf_data['password'], conf_data['host'], conf_data['port']
|
26
|
+
m_engine = mysql.MysqlUpload(
|
27
|
+
username=username,
|
28
|
+
password=password,
|
29
|
+
host=host,
|
30
|
+
port=port,
|
31
|
+
charset='utf8mb4'
|
32
|
+
)
|
33
|
+
conf_data = conf['Windows']['company']['mysql']['local']
|
34
|
+
username, password, host, port = conf_data['username'], conf_data['password'], conf_data['host'], conf_data['port']
|
35
|
+
company_engine = mysql.MysqlUpload(
|
36
|
+
username=username,
|
37
|
+
password=password,
|
38
|
+
host=host,
|
39
|
+
port=port,
|
40
|
+
charset='utf8mb4'
|
41
|
+
)
|
42
|
+
targe_host = 'company'
|
43
|
+
|
44
|
+
else:
|
45
|
+
conf = myconfig.main()
|
46
|
+
|
47
|
+
conf_data = conf['Windows']['company']['mysql']['remoto']
|
48
|
+
username, password, host, port = conf_data['username'], conf_data['password'], conf_data['host'], conf_data['port']
|
49
|
+
company_engine = mysql.MysqlUpload(
|
50
|
+
username=username,
|
51
|
+
password=password,
|
52
|
+
host=host,
|
53
|
+
port=port,
|
54
|
+
charset='utf8mb4'
|
55
|
+
)
|
56
|
+
|
57
|
+
conf_data = conf['Windows']['xigua_lx']['mysql']['local']
|
58
|
+
username, password, host, port = conf_data['username'], conf_data['password'], conf_data['host'], conf_data['port']
|
59
|
+
m_engine = mysql.MysqlUpload(
|
60
|
+
username=username,
|
61
|
+
password=password,
|
62
|
+
host=host,
|
63
|
+
port=port,
|
64
|
+
charset='utf8mb4'
|
65
|
+
)
|
66
|
+
targe_host = 'xigua_lx'
|
67
|
+
|
68
|
+
|
69
|
+
# def getdata():
|
70
|
+
# download = s_query.QueryDatas(username=username, password=password, host=host, port=port)
|
71
|
+
# start_date, end_date = '2024-01-01', '2024-12-20'
|
72
|
+
# projection = {
|
73
|
+
# '日期': 1,
|
74
|
+
# '三级来源': 1,
|
75
|
+
# '访客数': 1,
|
76
|
+
# }
|
77
|
+
# __res = []
|
78
|
+
# for year in range(2024, datetime.datetime.today().year + 1):
|
79
|
+
# df = download.data_to_df(
|
80
|
+
# db_name='聚合数据',
|
81
|
+
# table_name=f'店铺流量来源构成',
|
82
|
+
# start_date=start_date,
|
83
|
+
# end_date=end_date,
|
84
|
+
# projection=projection,
|
85
|
+
# )
|
86
|
+
# __res.append(df)
|
87
|
+
# df = pd.concat(__res, ignore_index=True)
|
88
|
+
# return df
|
89
|
+
|
90
|
+
|
91
|
+
class DataShow:
|
92
|
+
def __init__(self):
|
93
|
+
self.path = '/Users/xigua/Downloads'
|
94
|
+
root = tk.Tk()
|
95
|
+
self.screen_width = root.winfo_screenwidth()
|
96
|
+
self.screen_height = root.winfo_screenheight()
|
97
|
+
root.destroy()
|
98
|
+
self.today = datetime.date.today()
|
99
|
+
self.start_date = (self.today - datetime.timedelta(days=15)).strftime('%Y-%m-%d')
|
100
|
+
self.end_date = (self.today - datetime.timedelta(days=1)).strftime('%Y-%m-%d')
|
101
|
+
|
102
|
+
def getdata(self, db_name, table_name, pro_list, start_date=None, end_date=None):
|
103
|
+
download = s_query.QueryDatas(username=username, password=password, host=host, port=port)
|
104
|
+
if not start_date or not end_date:
|
105
|
+
start_date, end_date = '2000-01-01', '2099-12-31' # 从数据库提取数据,不能是 self.start_date
|
106
|
+
projection = {}
|
107
|
+
[projection.update({k: 1}) for k in pro_list]
|
108
|
+
__res = []
|
109
|
+
for year in range(2024, datetime.datetime.today().year + 1):
|
110
|
+
df = download.data_to_df(
|
111
|
+
db_name=db_name,
|
112
|
+
table_name=table_name,
|
113
|
+
start_date=start_date,
|
114
|
+
end_date=end_date,
|
115
|
+
projection=projection,
|
116
|
+
)
|
117
|
+
__res.append(df)
|
118
|
+
df = pd.concat(__res, ignore_index=True)
|
119
|
+
return df
|
120
|
+
|
121
|
+
def dpll_bak(self, db_name='聚合数据', table_name='店铺流量来源构成', pro_list=None, filename='店铺流量来源'):
|
122
|
+
if not pro_list:
|
123
|
+
pro_list = ['日期', '三级来源', '访客数']
|
124
|
+
df = self.getdata(db_name=db_name, table_name=table_name, pro_list=pro_list, start_date='2024-11-01', end_date=self.end_date)
|
125
|
+
if len(df) == 0:
|
126
|
+
print(f'数据不能为空: {table_name}')
|
127
|
+
return
|
128
|
+
df = df[df['三级来源'] != '汇总']
|
129
|
+
df['日期'] = pd.to_datetime(df['日期'])
|
130
|
+
today = datetime.date.today()
|
131
|
+
|
132
|
+
def st_date(num=1):
|
133
|
+
return pd.to_datetime(today - datetime.timedelta(days=num))
|
134
|
+
max_date = df['日期'].max().strftime('%Y-%m-%d')
|
135
|
+
df1 = df[df['日期'] >= st_date(1)]
|
136
|
+
df2 = df[df['日期'] >= st_date(7)]
|
137
|
+
df3 = df[df['日期'] >= st_date(30)]
|
138
|
+
df2 = df2.groupby(
|
139
|
+
['三级来源'],
|
140
|
+
as_index=False).agg(
|
141
|
+
**{
|
142
|
+
'访客数': ('访客数', np.sum),
|
143
|
+
}
|
144
|
+
)
|
145
|
+
df3 = df3.groupby(
|
146
|
+
['三级来源'],
|
147
|
+
as_index=False).agg(
|
148
|
+
**{
|
149
|
+
'访客数': ('访客数', np.sum),
|
150
|
+
}
|
151
|
+
)
|
152
|
+
# print(df)
|
153
|
+
labels1 = df1['三级来源'].tolist()
|
154
|
+
values1 = df1['访客数'].tolist()
|
155
|
+
labels2 = df2['三级来源'].tolist()
|
156
|
+
values2 = df2['访客数'].tolist()
|
157
|
+
labels3 = df3['三级来源'].tolist()
|
158
|
+
values3 = df3['访客数'].tolist()
|
159
|
+
|
160
|
+
def make_sub(data_list, num):
|
161
|
+
# 创建一个具有1行2列的网格布局
|
162
|
+
t_p = []
|
163
|
+
for i in range(num):
|
164
|
+
t_p.extend([{"type": "pie"}])
|
165
|
+
fig = make_subplots(rows=1, cols=num, specs=[t_p])
|
166
|
+
pie_title = {1: 1, 2: 7, 3: 30}
|
167
|
+
i = 1
|
168
|
+
for item in data_list:
|
169
|
+
# 计算每个扇区的百分比,并找出哪些扇区应该被保留
|
170
|
+
total = sum(item['值'])
|
171
|
+
# 计算每个扇区的百分比,并找出哪些扇区应该被保留
|
172
|
+
threshold_percentage = 0.1 # 阈值百分比
|
173
|
+
filtered_indices = [i for i, value in enumerate(item['值']) if
|
174
|
+
(value / total) * 100 >= threshold_percentage]
|
175
|
+
# 提取被保留的扇区的标签和值
|
176
|
+
filtered_labels = [item['键'][i] for i in filtered_indices]
|
177
|
+
filtered_values = [item['值'][i] for i in filtered_indices]
|
178
|
+
|
179
|
+
# 添加饼图
|
180
|
+
fig.add_trace(
|
181
|
+
go.Pie(labels=filtered_labels, values=filtered_values, name=f'pie {i}', textinfo='label+percent'),
|
182
|
+
row=1, col=i)
|
183
|
+
# fig.add_trace(go.Pie(labels=item['键'], values=item['值'], name=f'最近{pie_title[i]}天', textinfo='label+percent'), row=1, col=i)
|
184
|
+
fig.add_annotation(
|
185
|
+
text=f'最近{pie_title[i]}天',
|
186
|
+
x=0.15 + 0.35 * (i - 1),
|
187
|
+
y=0.98,
|
188
|
+
xref='paper', # # 相对于整个图表区域
|
189
|
+
yref='paper',
|
190
|
+
showarrow=True, # 显示箭头
|
191
|
+
align="left", # 文本对齐方式
|
192
|
+
font=dict(size=16),
|
193
|
+
)
|
194
|
+
i += 1
|
195
|
+
fig.update_layout(
|
196
|
+
title_text=f'店铺流量来源 最近一天: {max_date}',
|
197
|
+
xaxis_title='X Axis',
|
198
|
+
yaxis_title='Y Axis',
|
199
|
+
# width=self.screen_width // 1.4,
|
200
|
+
# height=self.screen_width // 2,
|
201
|
+
margin=dict(
|
202
|
+
l=100, # 左边距
|
203
|
+
r=300,
|
204
|
+
t=100, # 上边距
|
205
|
+
b=400,
|
206
|
+
),
|
207
|
+
)
|
208
|
+
fig.update_layout(xaxis_showgrid=False, yaxis_showgrid=False, xaxis_visible=False, yaxis_visible=False)
|
209
|
+
return fig
|
210
|
+
|
211
|
+
data_list = [{'键': labels1, '值': values1}, {'键': labels2, '值': values2}, {'键': labels3, '值': values3}]
|
212
|
+
fig = make_sub(data_list=data_list, num=3)
|
213
|
+
fig.write_html(os.path.join(self.path, f'{filename}.html'))
|
214
|
+
|
215
|
+
def dpll(self, db_name='聚合数据', table_name='店铺流量来源构成', pro_list=None, filename='店铺流量来源'):
|
216
|
+
if not pro_list:
|
217
|
+
pro_list = ['日期', '店铺名称', '类别', '来源构成', '二级来源', '三级来源', '访客数']
|
218
|
+
df = self.getdata(db_name=db_name, table_name=table_name, pro_list=pro_list, start_date='2024-11-01', end_date=self.end_date)
|
219
|
+
if len(df) == 0:
|
220
|
+
print(f'数据不能为空: {table_name}')
|
221
|
+
return
|
222
|
+
df['日期'] = pd.to_datetime(df['日期'])
|
223
|
+
df = df[
|
224
|
+
(df['店铺名称'] == '万里马官方旗舰店') &
|
225
|
+
(df['类别'] == '非全站推广期') &
|
226
|
+
(df['来源构成'] == '商品流量')
|
227
|
+
]
|
228
|
+
today = datetime.date.today()
|
229
|
+
|
230
|
+
def st_date(num=1):
|
231
|
+
return pd.to_datetime(today - datetime.timedelta(days=num))
|
232
|
+
max_date = df['日期'].max().strftime('%Y-%m-%d')
|
233
|
+
|
234
|
+
data_list = []
|
235
|
+
for days in [1, 7, 30]:
|
236
|
+
df_linshi = df[df['日期'] >= st_date(num=days)]
|
237
|
+
# 统计三级来源
|
238
|
+
df_linshi3 = df_linshi[df_linshi['二级来源'] != '汇总']
|
239
|
+
th_list = df_linshi3.groupby(['日期', '店铺名称', '类别', '来源构成', '二级来源']).size()
|
240
|
+
th_list = th_list.reset_index()
|
241
|
+
th_list = th_list[th_list[0] > 1]
|
242
|
+
th_list = th_list['二级来源'].tolist()
|
243
|
+
df_linshi3['三级来源'] = df_linshi3.apply(lambda x: x['三级来源'] if x['三级来源'] != '汇总' else '' if x['三级来源'] == '汇总' and x['二级来源'] in th_list else x['二级来源'], axis=1)
|
244
|
+
df_linshi3 = df_linshi3[df_linshi3['三级来源'] != '']
|
245
|
+
df_linshi3 = df_linshi3.groupby(['三级来源'], as_index=False).agg(**{'访客数': ('访客数', np.sum)})
|
246
|
+
|
247
|
+
df_linshi2 = df_linshi[(df_linshi['二级来源'] != '汇总') & (df_linshi['三级来源'] == '汇总')]
|
248
|
+
df_linshi2 = df_linshi2.groupby(['二级来源'], as_index=False).agg(**{'访客数': ('访客数', np.sum)})
|
249
|
+
data_list.append({'来源类型': '三级来源', '统计周期': days, '数据主体': df_linshi3})
|
250
|
+
data_list.append({'来源类型': '二级来源', '统计周期': days, '数据主体': df_linshi2})
|
251
|
+
# print(data_list)
|
252
|
+
t_p1 = []
|
253
|
+
for i in range(3):
|
254
|
+
t_p1.extend([{"type": "pie"}]) # 折线图类型
|
255
|
+
t_p2 = []
|
256
|
+
for i in range(3):
|
257
|
+
t_p2.extend([{"type": "pie"}]) # 饼图类型
|
258
|
+
specs = [t_p1, t_p2]
|
259
|
+
fig = make_subplots(rows=2, cols=3, specs=specs)
|
260
|
+
|
261
|
+
count1 = 0
|
262
|
+
count2 = 0
|
263
|
+
for item in data_list:
|
264
|
+
labels = item['数据主体'][item['来源类型']].tolist()
|
265
|
+
values = item['数据主体']['访客数'].tolist()
|
266
|
+
# 计算每个扇区的百分比,并找出哪些扇区应该被保留
|
267
|
+
total = sum(values)
|
268
|
+
# 计算每个扇区的百分比,并找出哪些扇区应该被保留
|
269
|
+
threshold_percentage = 1 # 阈值百分比
|
270
|
+
filtered_indices = [i for i, value in enumerate(values) if
|
271
|
+
(value / total) * 100 >= threshold_percentage]
|
272
|
+
# 提取被保留的扇区的标签和值
|
273
|
+
filtered_labels = [labels[i] for i in filtered_indices]
|
274
|
+
filtered_values = [values[i] for i in filtered_indices]
|
275
|
+
if item['来源类型'] == '二级来源':
|
276
|
+
# 添加饼图
|
277
|
+
fig.add_trace(
|
278
|
+
go.Pie(
|
279
|
+
labels=filtered_labels,
|
280
|
+
values=filtered_values,
|
281
|
+
name=item['来源类型'],
|
282
|
+
textinfo='label+percent'
|
283
|
+
),
|
284
|
+
row=1,
|
285
|
+
col=count1+1,
|
286
|
+
)
|
287
|
+
x = 0.14 + 0.355 * (count1)
|
288
|
+
y = 0.98
|
289
|
+
fig.add_annotation(
|
290
|
+
text=f'{item['来源类型']} 最近{item['统计周期']}天',
|
291
|
+
x=x,
|
292
|
+
y=y,
|
293
|
+
xref='paper', # # 相对于整个图表区域
|
294
|
+
yref='paper',
|
295
|
+
showarrow=True, # 显示箭头
|
296
|
+
align="left", # 文本对齐方式
|
297
|
+
font=dict(size=14),
|
298
|
+
)
|
299
|
+
count1 += 1
|
300
|
+
else:
|
301
|
+
# 添加饼图
|
302
|
+
fig.add_trace(
|
303
|
+
go.Pie(
|
304
|
+
labels=filtered_labels,
|
305
|
+
values=filtered_values,
|
306
|
+
name=item['来源类型'],
|
307
|
+
textinfo='label+percent'
|
308
|
+
),
|
309
|
+
row=2,
|
310
|
+
col=count2+1,
|
311
|
+
)
|
312
|
+
x = 0.12 + 0.39 * (count2 % 3)
|
313
|
+
y = -0.12
|
314
|
+
fig.add_annotation(
|
315
|
+
text=f'{item['来源类型']} 最近{item['统计周期']}天',
|
316
|
+
x=x,
|
317
|
+
y=y,
|
318
|
+
xref='paper', # # 相对于整个图表区域
|
319
|
+
yref='paper',
|
320
|
+
showarrow=False, # 显示箭头
|
321
|
+
align="left", # 文本对齐方式
|
322
|
+
font=dict(size=14),
|
323
|
+
)
|
324
|
+
count2 += 1
|
325
|
+
fig.update_layout(
|
326
|
+
title_text=f'店铺流量来源 最近数据: {max_date}',
|
327
|
+
# xaxis_title='X Axis',
|
328
|
+
# yaxis_title='Y Axis',
|
329
|
+
# width=self.screen_width // 1.4,
|
330
|
+
# height=self.screen_width // 2,
|
331
|
+
margin=dict(
|
332
|
+
l=100, # 左边距
|
333
|
+
r=100,
|
334
|
+
t=100, # 上边距
|
335
|
+
b=100,
|
336
|
+
),
|
337
|
+
legend=dict(
|
338
|
+
# title='Legend Title', # 图例标题
|
339
|
+
orientation='v', # 图例方向('h' 表示水平,'v' 表示垂直)
|
340
|
+
# x=0.5, # 图例在图表中的 x 位置(0 到 1 的比例)
|
341
|
+
# y=1.02, # 图例在图表中的 y 位置(稍微超出顶部以避免遮挡数据)
|
342
|
+
font=dict(
|
343
|
+
size=12 # 图例字体大小
|
344
|
+
)
|
345
|
+
)
|
346
|
+
)
|
347
|
+
fig.write_html(os.path.join(self.path, f'{filename}.html'))
|
348
|
+
|
349
|
+
def tg(self, db_name='聚合数据', table_name='多店推广场景_按日聚合', pro_list=None, filename='多店推广场景', days=None, start_date=None, end_date=None):
|
350
|
+
"""
|
351
|
+
:param db_name:
|
352
|
+
:param table_name:
|
353
|
+
:param pro_list:
|
354
|
+
:param filename:
|
355
|
+
:param days:
|
356
|
+
:param start_date: 如果指定,则 days 失效,如果都不指定,则设置 days = 7
|
357
|
+
:param end_date:
|
358
|
+
:return:
|
359
|
+
"""
|
360
|
+
if not pro_list:
|
361
|
+
pro_list = ['日期', '店铺名称', '营销场景', '花费', '成交金额']
|
362
|
+
df = self.getdata(db_name=db_name, table_name=table_name, pro_list=pro_list)
|
363
|
+
if len(df) == 0:
|
364
|
+
print(f'数据不能为空: {table_name}')
|
365
|
+
return
|
366
|
+
df['日期'] = pd.to_datetime(df['日期'])
|
367
|
+
today = datetime.date.today()
|
368
|
+
|
369
|
+
def st_date(num=1):
|
370
|
+
return pd.to_datetime(today - datetime.timedelta(days=num))
|
371
|
+
|
372
|
+
if start_date and end_date:
|
373
|
+
df = df[(df['日期'] >= pd.to_datetime(start_date)) & (df['日期'] <= pd.to_datetime(end_date))]
|
374
|
+
elif days:
|
375
|
+
df = df[df['日期'] >= st_date(num=days)]
|
376
|
+
else:
|
377
|
+
df = df[df['日期'] >= st_date(num=7)]
|
378
|
+
|
379
|
+
df = df.groupby(['日期', '店铺名称', '营销场景'], as_index=False).agg(**{'花费': ('花费', np.sum), '成交金额': ('成交金额', np.sum)})
|
380
|
+
max_date = df['日期'].max().strftime('%Y-%m-%d')
|
381
|
+
min_date = df['日期'].min().strftime('%Y-%m-%d')
|
382
|
+
df_other = df.groupby(['店铺名称'], as_index=False).agg(**{'花费': ('花费', np.sum)})
|
383
|
+
df_other = df_other.sort_values('花费', ascending=False)
|
384
|
+
data_list = []
|
385
|
+
for shopname in df_other['店铺名称'].tolist():
|
386
|
+
data_list.append(df[df['店铺名称'] == shopname])
|
387
|
+
# df1 = df[df['店铺名称'] == '万里马官方旗舰店']
|
388
|
+
# df2 = df[df['店铺名称'] == '万里马官方企业店']
|
389
|
+
# df3 = df[df['店铺名称'] == '京东箱包旗舰店']
|
390
|
+
# data_list = [df1, df2, df3]
|
391
|
+
|
392
|
+
def make_sub(data_list):
|
393
|
+
steps = len(data_list)
|
394
|
+
specs = []
|
395
|
+
t_p1 = []
|
396
|
+
for i in range(steps):
|
397
|
+
t_p1.extend([{"type": "xy"}]) # 折线图类型
|
398
|
+
t_p2 = []
|
399
|
+
for i in range(steps):
|
400
|
+
t_p2.extend([{"type": "pie"}]) # 饼图类型
|
401
|
+
specs = [t_p1, t_p2]
|
402
|
+
|
403
|
+
# 创建一个包含两个子图的图表,子图排列为1行2列
|
404
|
+
fig = make_subplots(
|
405
|
+
rows=2,
|
406
|
+
cols=steps,
|
407
|
+
specs=specs, # 注意 specs 是用列表传入
|
408
|
+
# subplot_titles=("First Line Chart", "Second Line Chart")
|
409
|
+
)
|
410
|
+
count = 1
|
411
|
+
for df in data_list:
|
412
|
+
shop = df['店铺名称'].tolist()[0]
|
413
|
+
# 在第 1 行添加折线图
|
414
|
+
scences = df['营销场景'].unique()
|
415
|
+
for scence in scences:
|
416
|
+
df_inside = df[df['营销场景'] == scence]
|
417
|
+
# if len(df_inside) < 7:
|
418
|
+
# continue
|
419
|
+
fig.add_trace(go.Scatter(x=df_inside['日期'].tolist(), y=df_inside['花费'].tolist(), mode='lines', name=f'{scence}_{shop}'), row=1, col=count)
|
420
|
+
# 在第 2 行添加饼图
|
421
|
+
df = df.groupby(['营销场景'], as_index=False).agg(**{'花费': ('花费', np.sum)})
|
422
|
+
labels = df['营销场景'].tolist()
|
423
|
+
values = df['花费'].tolist()
|
424
|
+
fig.add_trace(go.Pie(labels=labels, values=values, name=shop, textinfo='label+percent'), row=2, col=count)
|
425
|
+
fig.add_annotation(
|
426
|
+
text=shop,
|
427
|
+
x=0.01 + 0.395 * (count - 1),
|
428
|
+
y=1.04,
|
429
|
+
xref='paper', # # 相对于整个图表区域
|
430
|
+
yref='paper',
|
431
|
+
showarrow=False, # 显示箭头
|
432
|
+
align="left", # 文本对齐方式
|
433
|
+
font=dict(size=16),
|
434
|
+
)
|
435
|
+
count += 1
|
436
|
+
return fig
|
437
|
+
|
438
|
+
fig = make_sub(data_list=data_list)
|
439
|
+
fig.add_annotation(
|
440
|
+
text=f'统计范围: {min_date} ~ {max_date}',
|
441
|
+
x=0.5,
|
442
|
+
y=-0.15,
|
443
|
+
xref='paper', # # 相对于整个图表区域
|
444
|
+
yref='paper',
|
445
|
+
showarrow=False, # 显示箭头
|
446
|
+
align="left", # 文本对齐方式
|
447
|
+
font=dict(size=16),
|
448
|
+
)
|
449
|
+
fig.update_layout(
|
450
|
+
title_text=f'多店推广花费_按日聚合',
|
451
|
+
xaxis_title='日期',
|
452
|
+
yaxis_title='花费',
|
453
|
+
# width=self.screen_width // 1.4,
|
454
|
+
# height=self.screen_width // 2,
|
455
|
+
margin=dict(
|
456
|
+
l=100, # 左边距
|
457
|
+
r=100,
|
458
|
+
t=100, # 上边距
|
459
|
+
b=150,
|
460
|
+
),
|
461
|
+
# legend=dict(orientation="h")
|
462
|
+
)
|
463
|
+
count = 1
|
464
|
+
for item in data_list:
|
465
|
+
roi = round(item['成交金额'].sum() / item['花费'].sum(), 2)
|
466
|
+
fig.add_annotation(
|
467
|
+
text=f'合计: {int(item['花费'].sum())}元 / roi: {roi}',
|
468
|
+
x=0.15 + 0.425 * (count - 1),
|
469
|
+
y=1.04,
|
470
|
+
xref='paper', # # 相对于整个图表区域
|
471
|
+
yref='paper',
|
472
|
+
showarrow=False, # 显示箭头
|
473
|
+
align="left", # 文本对齐方式
|
474
|
+
font=dict(size=16),
|
475
|
+
)
|
476
|
+
count += 1
|
477
|
+
fig.write_html(os.path.join(self.path, f'{filename}.html'))
|
478
|
+
|
479
|
+
def item_crowd(self, db_name='商品人群画像2', table_list=None, pro_list=None, filename='商品人群画像', item_id=None, lab='全部渠道', option='商详浏览', d_str='近30天', last_date=None):
|
480
|
+
# item_ids = [696017020186, 714066010148, 830890472575]
|
481
|
+
if not pro_list:
|
482
|
+
pro_list = ['日期', '店铺名称', '洞察类型', '行为类型', '商品id', '统计周期', '标签名称', '标签人群数量']
|
483
|
+
if not table_list:
|
484
|
+
table_list = [
|
485
|
+
'消费能力等级',
|
486
|
+
'用户年龄',
|
487
|
+
'月均消费金额',
|
488
|
+
'大快消策略人群',
|
489
|
+
'店铺潜新老客',
|
490
|
+
'城市等级',
|
491
|
+
'用户职业',
|
492
|
+
]
|
493
|
+
if not item_id:
|
494
|
+
item_id = 696017020186
|
495
|
+
dict_list = {}
|
496
|
+
for table_name in table_list:
|
497
|
+
df = self.getdata(db_name=db_name, table_name=table_name, pro_list=pro_list)
|
498
|
+
if len(df) == 0:
|
499
|
+
print(f'{table_name}: 数据长度不能为 0')
|
500
|
+
continue
|
501
|
+
df['日期'] = pd.to_datetime(df['日期'])
|
502
|
+
df['商品id'] = df['商品id'].astype('int64')
|
503
|
+
df = df[df['商品id'] == int(item_id)]
|
504
|
+
last_date = df['日期'].max()
|
505
|
+
# 对数据进行筛选
|
506
|
+
df = df[
|
507
|
+
(df['日期'] == last_date) &
|
508
|
+
~df['标签名称'].str.contains('unknown', case=False) &
|
509
|
+
(df['洞察类型'] == lab) &
|
510
|
+
(df['行为类型'] == option) &
|
511
|
+
(df['统计周期'] == d_str)
|
512
|
+
]
|
513
|
+
dict_list.update({table_name: df})
|
514
|
+
|
515
|
+
fig = make_subplots(rows=2, cols=3)
|
516
|
+
# 在每个子图中绘制柱形图
|
517
|
+
count = 0
|
518
|
+
for table_name, df in dict_list.items():
|
519
|
+
if len(df) == 0:
|
520
|
+
count += 1
|
521
|
+
continue
|
522
|
+
# print(count, table_name)
|
523
|
+
if count > 5:
|
524
|
+
break
|
525
|
+
labels = df['标签名称'].tolist()
|
526
|
+
values = df['标签人群数量'].tolist()
|
527
|
+
df['Percentage'] = df['标签人群数量'] / df['标签人群数量'].sum() * 100
|
528
|
+
percentages = df['Percentage']
|
529
|
+
bar = go.Bar(
|
530
|
+
x=labels,
|
531
|
+
y=values,
|
532
|
+
name=table_name,
|
533
|
+
text=percentages.map('{:.2f}%'.format), # 设置要显示的文本(百分比)
|
534
|
+
# textposition = 'outside', # 设置文本位置在柱形图外部
|
535
|
+
)
|
536
|
+
row = count // 3 + 1
|
537
|
+
col = count % 3 + 1
|
538
|
+
fig.add_trace(
|
539
|
+
bar,
|
540
|
+
row=row,
|
541
|
+
col=col,
|
542
|
+
)
|
543
|
+
if count < 3:
|
544
|
+
x = 0.01 + 0.395 * (count)
|
545
|
+
y = 1.04
|
546
|
+
else:
|
547
|
+
x = 0.01 + 0.395 * (count % 3)
|
548
|
+
y = 1.04 - 0.59 * (count // 3)
|
549
|
+
fig.add_annotation(
|
550
|
+
text=table_name,
|
551
|
+
x=x,
|
552
|
+
y=y,
|
553
|
+
xref='paper', # # 相对于整个图表区域
|
554
|
+
yref='paper',
|
555
|
+
showarrow=False, # 显示箭头
|
556
|
+
align="left", # 文本对齐方式
|
557
|
+
font=dict(size=16),
|
558
|
+
)
|
559
|
+
count += 1
|
560
|
+
|
561
|
+
fig.update_layout(
|
562
|
+
title_text=f'{db_name} 商品id: {item_id}',
|
563
|
+
xaxis_title='标签',
|
564
|
+
yaxis_title='人群数量',
|
565
|
+
# width=self.screen_width // 1.4,
|
566
|
+
# height=self.screen_width // 2,
|
567
|
+
margin=dict(
|
568
|
+
l=100, # 左边距
|
569
|
+
r=100,
|
570
|
+
t=100, # 上边距
|
571
|
+
b=100,
|
572
|
+
),
|
573
|
+
# legend=dict(orientation="h")
|
574
|
+
)
|
575
|
+
fig.add_annotation(
|
576
|
+
text=f'数据日期: {last_date.strftime('%Y-%m-%d')} 统计范围: {lab}/{option} {d_str}',
|
577
|
+
x=0.5,
|
578
|
+
y=-0.1,
|
579
|
+
xref='paper', # # 相对于整个图表区域
|
580
|
+
yref='paper',
|
581
|
+
showarrow=False, # 显示箭头
|
582
|
+
align="left", # 文本对齐方式
|
583
|
+
font=dict(size=14),
|
584
|
+
)
|
585
|
+
fig.write_html(os.path.join(self.path, f'{filename}.html'))
|
586
|
+
|
587
|
+
|
588
|
+
def main():
|
589
|
+
ds = DataShow()
|
590
|
+
# ds.dpll()
|
591
|
+
# ds.tg(
|
592
|
+
# days=15,
|
593
|
+
# # start_date='2024-11-01',
|
594
|
+
# # end_date='2024-11-30',
|
595
|
+
# )
|
596
|
+
ds.item_crowd(
|
597
|
+
item_id=839148235697,
|
598
|
+
lab='全部渠道',
|
599
|
+
option='商详浏览',
|
600
|
+
last_date=None,
|
601
|
+
d_str='近30天',
|
602
|
+
)
|
603
|
+
|
604
|
+
|
605
|
+
if __name__ == '__main__':
|
606
|
+
main()
|
mdbq/aggregation/query_data.py
CHANGED
@@ -3806,4 +3806,9 @@ if __name__ == '__main__':
|
|
3806
3806
|
# is_mysql=True,
|
3807
3807
|
# )
|
3808
3808
|
|
3809
|
-
query3(months=2, less_dict=[])
|
3809
|
+
# query3(months=2, less_dict=[])
|
3810
|
+
|
3811
|
+
sdq = MysqlDatasQuery() # 实例化数据处理类
|
3812
|
+
sdq.months = 100 # 设置数据周期, 1 表示近 2 个月
|
3813
|
+
sdq.update_service = True # 调试时加,true: 将数据写入 mysql 服务器
|
3814
|
+
sdq.dplyd(db_name='聚合数据', table_name='店铺流量来源构成')
|
mdbq/spider/aikucun.py
CHANGED
@@ -2,8 +2,9 @@ mdbq/__init__.py,sha256=Il5Q9ATdX8yXqVxtP_nYqUhExzxPC_qk_WXQ_4h0exg,16
|
|
2
2
|
mdbq/__version__.py,sha256=y9Mp_8x0BCZSHsdLT_q5tX9wZwd5QgqrSIENLrb6vXA,62
|
3
3
|
mdbq/aggregation/__init__.py,sha256=EeDqX2Aml6SPx8363J-v1lz0EcZtgwIBYyCJV6CcEDU,40
|
4
4
|
mdbq/aggregation/aggregation.py,sha256=-yzApnlqSN2L0E1YMu5ml-W827qpKQvWPCOI7jj2kzY,80264
|
5
|
+
mdbq/aggregation/datashow.py,sha256=sNZYwhPraF3KmcYdBVKvVaVoN-jGjh7ALRRLpanzQ6w,25673
|
5
6
|
mdbq/aggregation/optimize_data.py,sha256=RXIv7cACCgYyehAxMjUYi_S7rVyjIwXKWMaM3nduGtA,3068
|
6
|
-
mdbq/aggregation/query_data.py,sha256=
|
7
|
+
mdbq/aggregation/query_data.py,sha256=4Fd4dMGi6Cu-KgNTf1OBNYe8InjvpMA5JALxCwvsHyw,173841
|
7
8
|
mdbq/bdup/__init__.py,sha256=AkhsGk81SkG1c8FqDH5tRq-8MZmFobVbN60DTyukYTY,28
|
8
9
|
mdbq/bdup/bdup.py,sha256=LAV0TgnQpc-LB-YuJthxb0U42_VkPidzQzAagan46lU,4234
|
9
10
|
mdbq/config/__init__.py,sha256=jso1oHcy6cJEfa7udS_9uO5X6kZLoPBF8l3wCYmr5dM,18
|
@@ -32,8 +33,8 @@ mdbq/pbix/pbix_refresh.py,sha256=JUjKW3bNEyoMVfVfo77UhguvS5AWkixvVhDbw4_MHco,239
|
|
32
33
|
mdbq/pbix/refresh_all.py,sha256=OBT9EewSZ0aRS9vL_FflVn74d4l2G00wzHiikCC4TC0,5926
|
33
34
|
mdbq/pbix/refresh_all_old.py,sha256=_pq3WSQ728GPtEG5pfsZI2uTJhU8D6ra-htIk1JXYzw,7192
|
34
35
|
mdbq/spider/__init__.py,sha256=RBMFXGy_jd1HXZhngB2T2XTvJqki8P_Fr-pBcwijnew,18
|
35
|
-
mdbq/spider/aikucun.py,sha256=
|
36
|
-
mdbq-3.3.
|
37
|
-
mdbq-3.3.
|
38
|
-
mdbq-3.3.
|
39
|
-
mdbq-3.3.
|
36
|
+
mdbq/spider/aikucun.py,sha256=eAIITxnbbxsR_EoohJ78CRw2dEdfSHOltfpxBrh0cvc,22207
|
37
|
+
mdbq-3.3.15.dist-info/METADATA,sha256=ZoivLw_LLapTkSRtAZGP2xvD8jpaBpX53MrIGKJ_LkQ,244
|
38
|
+
mdbq-3.3.15.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
|
39
|
+
mdbq-3.3.15.dist-info/top_level.txt,sha256=2FQ-uLnCSB-OwFiWntzmwosW3X2Xqsg0ewh1axsaylA,5
|
40
|
+
mdbq-3.3.15.dist-info/RECORD,,
|
File without changes
|
File without changes
|