pyxllib 0.3.197__py3-none-any.whl → 0.3.200__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.
Files changed (126) hide show
  1. pyxllib/__init__.py +21 -21
  2. pyxllib/algo/__init__.py +8 -8
  3. pyxllib/algo/disjoint.py +54 -54
  4. pyxllib/algo/geo.py +541 -541
  5. pyxllib/algo/intervals.py +964 -964
  6. pyxllib/algo/matcher.py +389 -389
  7. pyxllib/algo/newbie.py +166 -166
  8. pyxllib/algo/pupil.py +629 -629
  9. pyxllib/algo/shapelylib.py +67 -67
  10. pyxllib/algo/specialist.py +241 -241
  11. pyxllib/algo/stat.py +494 -494
  12. pyxllib/algo/treelib.py +149 -149
  13. pyxllib/algo/unitlib.py +66 -66
  14. pyxllib/autogui/__init__.py +5 -5
  15. pyxllib/autogui/activewin.py +246 -246
  16. pyxllib/autogui/all.py +9 -9
  17. pyxllib/autogui/autogui.py +852 -852
  18. pyxllib/autogui/uiautolib.py +362 -362
  19. pyxllib/autogui/virtualkey.py +102 -102
  20. pyxllib/autogui/wechat.py +827 -827
  21. pyxllib/autogui/wechat_msg.py +421 -421
  22. pyxllib/autogui/wxautolib.py +84 -84
  23. pyxllib/cv/__init__.py +5 -5
  24. pyxllib/cv/expert.py +267 -267
  25. pyxllib/cv/imfile.py +159 -159
  26. pyxllib/cv/imhash.py +39 -39
  27. pyxllib/cv/pupil.py +9 -9
  28. pyxllib/cv/rgbfmt.py +1525 -1525
  29. pyxllib/cv/slidercaptcha.py +137 -137
  30. pyxllib/cv/trackbartools.py +251 -251
  31. pyxllib/cv/xlcvlib.py +1040 -1040
  32. pyxllib/cv/xlpillib.py +423 -423
  33. pyxllib/data/echarts.py +240 -240
  34. pyxllib/data/jsonlib.py +89 -89
  35. pyxllib/data/oss.py +72 -72
  36. pyxllib/data/pglib.py +1127 -1127
  37. pyxllib/data/sqlite.py +568 -568
  38. pyxllib/data/sqllib.py +297 -297
  39. pyxllib/ext/JLineViewer.py +505 -505
  40. pyxllib/ext/__init__.py +6 -6
  41. pyxllib/ext/demolib.py +246 -246
  42. pyxllib/ext/drissionlib.py +277 -277
  43. pyxllib/ext/kq5034lib.py +12 -12
  44. pyxllib/ext/old.py +663 -663
  45. pyxllib/ext/qt.py +449 -449
  46. pyxllib/ext/robustprocfile.py +497 -497
  47. pyxllib/ext/seleniumlib.py +76 -76
  48. pyxllib/ext/tk.py +173 -173
  49. pyxllib/ext/unixlib.py +827 -827
  50. pyxllib/ext/utools.py +351 -351
  51. pyxllib/ext/webhook.py +124 -119
  52. pyxllib/ext/win32lib.py +40 -40
  53. pyxllib/ext/wjxlib.py +88 -88
  54. pyxllib/ext/wpsapi.py +124 -124
  55. pyxllib/ext/xlwork.py +9 -9
  56. pyxllib/ext/yuquelib.py +1105 -1105
  57. pyxllib/file/__init__.py +17 -17
  58. pyxllib/file/docxlib.py +761 -761
  59. pyxllib/file/gitlib.py +309 -309
  60. pyxllib/file/libreoffice.py +165 -165
  61. pyxllib/file/movielib.py +148 -148
  62. pyxllib/file/newbie.py +10 -10
  63. pyxllib/file/onenotelib.py +1469 -1469
  64. pyxllib/file/packlib/__init__.py +330 -330
  65. pyxllib/file/packlib/zipfile.py +2441 -2441
  66. pyxllib/file/pdflib.py +426 -426
  67. pyxllib/file/pupil.py +185 -185
  68. pyxllib/file/specialist/__init__.py +685 -685
  69. pyxllib/file/specialist/dirlib.py +799 -799
  70. pyxllib/file/specialist/download.py +193 -193
  71. pyxllib/file/specialist/filelib.py +2829 -2829
  72. pyxllib/file/xlsxlib.py +3131 -3131
  73. pyxllib/file/xlsyncfile.py +341 -341
  74. pyxllib/prog/__init__.py +5 -5
  75. pyxllib/prog/cachetools.py +64 -64
  76. pyxllib/prog/deprecatedlib.py +233 -233
  77. pyxllib/prog/filelock.py +42 -42
  78. pyxllib/prog/ipyexec.py +253 -253
  79. pyxllib/prog/multiprogs.py +940 -940
  80. pyxllib/prog/newbie.py +451 -451
  81. pyxllib/prog/pupil.py +1197 -1197
  82. pyxllib/prog/sitepackages.py +33 -33
  83. pyxllib/prog/specialist/__init__.py +391 -391
  84. pyxllib/prog/specialist/bc.py +203 -203
  85. pyxllib/prog/specialist/browser.py +497 -497
  86. pyxllib/prog/specialist/common.py +347 -347
  87. pyxllib/prog/specialist/datetime.py +198 -198
  88. pyxllib/prog/specialist/tictoc.py +240 -240
  89. pyxllib/prog/specialist/xllog.py +180 -180
  90. pyxllib/prog/xlosenv.py +108 -108
  91. pyxllib/stdlib/__init__.py +17 -17
  92. pyxllib/stdlib/tablepyxl/__init__.py +10 -10
  93. pyxllib/stdlib/tablepyxl/style.py +303 -303
  94. pyxllib/stdlib/tablepyxl/tablepyxl.py +130 -130
  95. pyxllib/text/__init__.py +8 -8
  96. pyxllib/text/ahocorasick.py +39 -39
  97. pyxllib/text/airscript.js +744 -744
  98. pyxllib/text/charclasslib.py +121 -121
  99. pyxllib/text/jiebalib.py +267 -267
  100. pyxllib/text/jinjalib.py +32 -32
  101. pyxllib/text/jsa_ai_prompt.md +271 -271
  102. pyxllib/text/jscode.py +922 -922
  103. pyxllib/text/latex/__init__.py +158 -158
  104. pyxllib/text/levenshtein.py +303 -303
  105. pyxllib/text/nestenv.py +1215 -1215
  106. pyxllib/text/newbie.py +300 -300
  107. pyxllib/text/pupil/__init__.py +8 -8
  108. pyxllib/text/pupil/common.py +1121 -1121
  109. pyxllib/text/pupil/xlalign.py +326 -326
  110. pyxllib/text/pycode.py +47 -47
  111. pyxllib/text/specialist/__init__.py +8 -8
  112. pyxllib/text/specialist/common.py +112 -112
  113. pyxllib/text/specialist/ptag.py +186 -186
  114. pyxllib/text/spellchecker.py +172 -172
  115. pyxllib/text/templates/echart_base.html +10 -10
  116. pyxllib/text/templates/highlight_code.html +16 -16
  117. pyxllib/text/templates/latex_editor.html +102 -102
  118. pyxllib/text/vbacode.py +17 -17
  119. pyxllib/text/xmllib.py +747 -747
  120. pyxllib/xl.py +42 -39
  121. pyxllib/xlcv.py +17 -17
  122. {pyxllib-0.3.197.dist-info → pyxllib-0.3.200.dist-info}/METADATA +1 -1
  123. pyxllib-0.3.200.dist-info/RECORD +126 -0
  124. {pyxllib-0.3.197.dist-info → pyxllib-0.3.200.dist-info}/licenses/LICENSE +190 -190
  125. pyxllib-0.3.197.dist-info/RECORD +0 -126
  126. {pyxllib-0.3.197.dist-info → pyxllib-0.3.200.dist-info}/WHEEL +0 -0
pyxllib/data/echarts.py CHANGED
@@ -1,240 +1,240 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- # @Author : 陈坤泽
4
- # @Email : 877362867@qq.com
5
- # @Date : 2022/02/09 11:14
6
-
7
-
8
- """
9
- Apache ECharts: https://echarts.apache.org/zh/index.html
10
- python版:pyechats的封装
11
- """
12
-
13
- from pyxllib.prog.pupil import check_install_package
14
-
15
- check_install_package('pyecharts')
16
-
17
- # import types
18
-
19
- import pyecharts
20
- from pyecharts import options as opts
21
- from pyecharts.commons.utils import JsCode
22
- from pyecharts.globals import ChartType
23
- from pyecharts import types
24
- from pyecharts.charts import Bar, Line, Radar
25
- from pyecharts.charts.chart import Chart
26
-
27
- from pyxllib.prog.pupil import inject_members
28
- from pyxllib.prog.specialist import TicToc
29
- from pyxllib.file.specialist import XlPath
30
-
31
-
32
- class XlChart(Chart):
33
- def set_title(self, title):
34
- self.set_global_opts(title_opts=pyecharts.options.TitleOpts(title=title))
35
-
36
- def add_series(self, name, data, *, type=None, color=None, labels=None,
37
- **kwargs):
38
- """ 垃圾pyecharts,毁我青春~~
39
-
40
- 很多图x都不是等间距的,pyecharts处理不等间距x好像有很大的不兼容问题
41
- 需要手动添加x、y坐标位置
42
-
43
- :param list|tuple labels: 直接提供现成的文本标签
44
-
45
- """
46
- if type is None:
47
- type = self.__class__.__name__.lower()
48
-
49
- if labels:
50
- s = [[x[0][0], x[1]] for x in zip(data, labels)]
51
- fmt = JsCode(f"function(x){{var m = new Map({s}); return m.get(x.value[0]);}}")
52
- if 'label' not in kwargs:
53
- kwargs['label'] = opts.LabelOpts(is_show=True, formatter=fmt)
54
- elif isinstance(kwargs['label'], opts.LabelOpts):
55
- kwargs['label'].opts['formatter'] = fmt
56
- else:
57
- kwargs['label']['show'] = True
58
- kwargs['label']['formatter'] = fmt
59
-
60
- self._append_color(color)
61
- # self._append_legend(name, is_selected=True)
62
- self._append_legend(name)
63
-
64
- self.options.get('series').append(
65
- {
66
- 'type': type,
67
- 'name': name,
68
- 'data': data,
69
- **kwargs,
70
- }
71
- )
72
- return self
73
-
74
-
75
- inject_members(XlChart, Chart)
76
-
77
-
78
- class XlLine(Line):
79
- @classmethod
80
- def from_dict(cls, yaxis, xaxis=None, *, title=None,
81
- xaxis_name=None, yaxis_name=None, **kwargs):
82
- """ 查看一个数据的折线图
83
-
84
- :param list|dict yaxis: 列表数据,或者字典name: values表示的多组数据
85
- """
86
- c = cls()
87
-
88
- if isinstance(yaxis, (list, tuple)):
89
- yaxis = {'value': yaxis}
90
- if xaxis is None:
91
- xaxis = list(range(max([len(v) for v in yaxis.values()])))
92
- c.add_xaxis(xaxis)
93
- for k, v in yaxis.items():
94
- c.add_yaxis(k, v)
95
-
96
- configs = {
97
- 'tooltip_opts': opts.TooltipOpts(trigger="axis"),
98
- **kwargs,
99
- }
100
- c.set_global_opts(tooltip_opts=opts.TooltipOpts(trigger="axis"))
101
- if title:
102
- configs['title_opts'] = opts.TitleOpts(title=title)
103
- if xaxis_name:
104
- configs['xaxis_opts'] = opts.AxisOpts(name=xaxis_name, axislabel_opts=opts.LabelOpts(rotate=45, interval=0))
105
- if yaxis_name:
106
- configs['yaxis_opts'] = opts.AxisOpts(name=yaxis_name)
107
- c.set_global_opts(**configs)
108
- return c
109
-
110
-
111
- class XlBar(Bar):
112
-
113
- @classmethod
114
- def from_dict(cls, yaxis, xaxis=None, *, title=None,
115
- xaxis_name=None, yaxis_name=None, **kwargs):
116
- """ 查看一个数据的条形图
117
-
118
- :param list|dict yaxis: 列表数据,或者字典name: values表示的多组数据
119
- """
120
- c = cls()
121
-
122
- if isinstance(yaxis, (list, tuple)):
123
- yaxis = {'value': yaxis}
124
- if xaxis is None:
125
- xaxis = list(range(max([len(v) for v in yaxis.values()])))
126
- c.add_xaxis(xaxis)
127
- for k, v in yaxis.items():
128
- c.add_yaxis(k, v)
129
-
130
- configs = {
131
- 'tooltip_opts': opts.TooltipOpts(trigger="axis"),
132
- **kwargs,
133
- }
134
- c.set_global_opts(tooltip_opts=opts.TooltipOpts(trigger="axis"))
135
- if title:
136
- configs['title_opts'] = opts.TitleOpts(title=title)
137
- if xaxis_name:
138
- configs['xaxis_opts'] = opts.AxisOpts(name=xaxis_name)
139
- if yaxis_name:
140
- configs['yaxis_opts'] = opts.AxisOpts(name=yaxis_name)
141
- c.set_global_opts(**configs)
142
- return c
143
-
144
- @classmethod
145
- def from_list(cls, yaxis, xaxis=None, *, title=None):
146
- """
147
- >> browser(pyecharts.charts.Bar.from_list(numbers))
148
- """
149
- return cls.from_dict({'value': list(yaxis)}, xaxis=xaxis, title=title)
150
-
151
- @classmethod
152
- def from_data_split_into_groups(cls, data, groups, *, title=None):
153
- """根据给定的组数自动拆分数据并生成条形图
154
- :param list data: 数据清单
155
- :param int groups: 要拆分成的组数
156
- """
157
- # 找到最大值和最小值
158
- min_val, max_val = min(data), max(data)
159
-
160
- # 计算间隔
161
- interval = (max_val - min_val) / groups
162
-
163
- # 分组和标签
164
- group_counts = [0] * groups
165
- labels = []
166
- # todo 如果数据量特别大,这里应该排序后,再用特殊方法计算分组
167
- for value in data:
168
- index = min(int((value - min_val) / interval), groups - 1)
169
- group_counts[index] += 1
170
-
171
- for i in range(groups):
172
- labels.append(f"{min_val + interval * i:.2f}-{min_val + interval * (i + 1):.2f}")
173
- # t = cls.from_dict({'value': group_counts}, xaxis=labels, title=title)
174
-
175
- return cls.from_dict({'value': group_counts}, xaxis=labels, title=title)
176
-
177
-
178
- class XlRadar(Radar):
179
- """ 雷达图 """
180
-
181
- def __init__(self, *args, **kwargs):
182
- super().__init__(*args, **kwargs)
183
- self.color_idx = 0
184
-
185
- def add(
186
- self,
187
- series_name: str,
188
- data: types.Sequence[types.Union[opts.RadarItem, dict]],
189
- *,
190
- label_opts=None,
191
- color: types.Optional[str] = None,
192
- linestyle_opts=None,
193
- **kwargs
194
- ):
195
- """ 标准库(2.0.5版)的雷达图颜色渲染有问题,这里要增加一个修正过程 """
196
- if label_opts is None:
197
- label_opts = opts.LabelOpts(is_show=False)
198
-
199
- if linestyle_opts is None:
200
- linestyle_opts = opts.LineStyleOpts(color=self.colors[self.color_idx % len(self.colors)])
201
- self.color_idx += 1
202
- elif linestyle_opts.get('color') is None:
203
- linestyle_opts.update(color=self.colors[self.color_idx % len(self.colors)])
204
- self.color_idx += 1
205
-
206
- if color is None:
207
- color = linestyle_opts.get('color')
208
-
209
- return super(XlRadar, self).add(series_name, data,
210
- label_opts=label_opts,
211
- color=color,
212
- linestyle_opts=linestyle_opts,
213
- **kwargs)
214
-
215
-
216
- inject_members(XlBar, Bar)
217
-
218
-
219
- def render_echart_html(title='Awesome-pyecharts', body=''):
220
- from pyxllib.text.xmllib import get_jinja_template
221
- return get_jinja_template('echart_base.html').render(title=title, body=body)
222
-
223
-
224
- # 绘制帕累托累计图
225
- def draw_pareto_chart(data, accuracy=0.1, *, title='帕累托累积权重', value_unit_type='K'):
226
- from pyxllib.algo.stat import pareto_accumulate
227
- pts, labels = pareto_accumulate(data, accuracy=accuracy, value_unit_type=value_unit_type)
228
- x = Line()
229
- x.add_series(title, pts, labels=labels, label={'position': 'right'})
230
- x.set_global_opts(
231
- # x轴末尾要故意撑大一些,不然有部分内容会显示不全
232
- xaxis_opts=opts.AxisOpts(name='条目数', max_=int(float(f'{pts[-1][0] * 1.2:.2g}'))),
233
- yaxis_opts=opts.AxisOpts(name='累积和')
234
- )
235
- return x
236
-
237
-
238
- if __name__ == '__main__':
239
- with TicToc(__name__):
240
- pass
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # @Author : 陈坤泽
4
+ # @Email : 877362867@qq.com
5
+ # @Date : 2022/02/09 11:14
6
+
7
+
8
+ """
9
+ Apache ECharts: https://echarts.apache.org/zh/index.html
10
+ python版:pyechats的封装
11
+ """
12
+
13
+ from pyxllib.prog.pupil import check_install_package
14
+
15
+ check_install_package('pyecharts')
16
+
17
+ # import types
18
+
19
+ import pyecharts
20
+ from pyecharts import options as opts
21
+ from pyecharts.commons.utils import JsCode
22
+ from pyecharts.globals import ChartType
23
+ from pyecharts import types
24
+ from pyecharts.charts import Bar, Line, Radar
25
+ from pyecharts.charts.chart import Chart
26
+
27
+ from pyxllib.prog.pupil import inject_members
28
+ from pyxllib.prog.specialist import TicToc
29
+ from pyxllib.file.specialist import XlPath
30
+
31
+
32
+ class XlChart(Chart):
33
+ def set_title(self, title):
34
+ self.set_global_opts(title_opts=pyecharts.options.TitleOpts(title=title))
35
+
36
+ def add_series(self, name, data, *, type=None, color=None, labels=None,
37
+ **kwargs):
38
+ """ 垃圾pyecharts,毁我青春~~
39
+
40
+ 很多图x都不是等间距的,pyecharts处理不等间距x好像有很大的不兼容问题
41
+ 需要手动添加x、y坐标位置
42
+
43
+ :param list|tuple labels: 直接提供现成的文本标签
44
+
45
+ """
46
+ if type is None:
47
+ type = self.__class__.__name__.lower()
48
+
49
+ if labels:
50
+ s = [[x[0][0], x[1]] for x in zip(data, labels)]
51
+ fmt = JsCode(f"function(x){{var m = new Map({s}); return m.get(x.value[0]);}}")
52
+ if 'label' not in kwargs:
53
+ kwargs['label'] = opts.LabelOpts(is_show=True, formatter=fmt)
54
+ elif isinstance(kwargs['label'], opts.LabelOpts):
55
+ kwargs['label'].opts['formatter'] = fmt
56
+ else:
57
+ kwargs['label']['show'] = True
58
+ kwargs['label']['formatter'] = fmt
59
+
60
+ self._append_color(color)
61
+ # self._append_legend(name, is_selected=True)
62
+ self._append_legend(name)
63
+
64
+ self.options.get('series').append(
65
+ {
66
+ 'type': type,
67
+ 'name': name,
68
+ 'data': data,
69
+ **kwargs,
70
+ }
71
+ )
72
+ return self
73
+
74
+
75
+ inject_members(XlChart, Chart)
76
+
77
+
78
+ class XlLine(Line):
79
+ @classmethod
80
+ def from_dict(cls, yaxis, xaxis=None, *, title=None,
81
+ xaxis_name=None, yaxis_name=None, **kwargs):
82
+ """ 查看一个数据的折线图
83
+
84
+ :param list|dict yaxis: 列表数据,或者字典name: values表示的多组数据
85
+ """
86
+ c = cls()
87
+
88
+ if isinstance(yaxis, (list, tuple)):
89
+ yaxis = {'value': yaxis}
90
+ if xaxis is None:
91
+ xaxis = list(range(max([len(v) for v in yaxis.values()])))
92
+ c.add_xaxis(xaxis)
93
+ for k, v in yaxis.items():
94
+ c.add_yaxis(k, v)
95
+
96
+ configs = {
97
+ 'tooltip_opts': opts.TooltipOpts(trigger="axis"),
98
+ **kwargs,
99
+ }
100
+ c.set_global_opts(tooltip_opts=opts.TooltipOpts(trigger="axis"))
101
+ if title:
102
+ configs['title_opts'] = opts.TitleOpts(title=title)
103
+ if xaxis_name:
104
+ configs['xaxis_opts'] = opts.AxisOpts(name=xaxis_name, axislabel_opts=opts.LabelOpts(rotate=45, interval=0))
105
+ if yaxis_name:
106
+ configs['yaxis_opts'] = opts.AxisOpts(name=yaxis_name)
107
+ c.set_global_opts(**configs)
108
+ return c
109
+
110
+
111
+ class XlBar(Bar):
112
+
113
+ @classmethod
114
+ def from_dict(cls, yaxis, xaxis=None, *, title=None,
115
+ xaxis_name=None, yaxis_name=None, **kwargs):
116
+ """ 查看一个数据的条形图
117
+
118
+ :param list|dict yaxis: 列表数据,或者字典name: values表示的多组数据
119
+ """
120
+ c = cls()
121
+
122
+ if isinstance(yaxis, (list, tuple)):
123
+ yaxis = {'value': yaxis}
124
+ if xaxis is None:
125
+ xaxis = list(range(max([len(v) for v in yaxis.values()])))
126
+ c.add_xaxis(xaxis)
127
+ for k, v in yaxis.items():
128
+ c.add_yaxis(k, v)
129
+
130
+ configs = {
131
+ 'tooltip_opts': opts.TooltipOpts(trigger="axis"),
132
+ **kwargs,
133
+ }
134
+ c.set_global_opts(tooltip_opts=opts.TooltipOpts(trigger="axis"))
135
+ if title:
136
+ configs['title_opts'] = opts.TitleOpts(title=title)
137
+ if xaxis_name:
138
+ configs['xaxis_opts'] = opts.AxisOpts(name=xaxis_name)
139
+ if yaxis_name:
140
+ configs['yaxis_opts'] = opts.AxisOpts(name=yaxis_name)
141
+ c.set_global_opts(**configs)
142
+ return c
143
+
144
+ @classmethod
145
+ def from_list(cls, yaxis, xaxis=None, *, title=None):
146
+ """
147
+ >> browser(pyecharts.charts.Bar.from_list(numbers))
148
+ """
149
+ return cls.from_dict({'value': list(yaxis)}, xaxis=xaxis, title=title)
150
+
151
+ @classmethod
152
+ def from_data_split_into_groups(cls, data, groups, *, title=None):
153
+ """根据给定的组数自动拆分数据并生成条形图
154
+ :param list data: 数据清单
155
+ :param int groups: 要拆分成的组数
156
+ """
157
+ # 找到最大值和最小值
158
+ min_val, max_val = min(data), max(data)
159
+
160
+ # 计算间隔
161
+ interval = (max_val - min_val) / groups
162
+
163
+ # 分组和标签
164
+ group_counts = [0] * groups
165
+ labels = []
166
+ # todo 如果数据量特别大,这里应该排序后,再用特殊方法计算分组
167
+ for value in data:
168
+ index = min(int((value - min_val) / interval), groups - 1)
169
+ group_counts[index] += 1
170
+
171
+ for i in range(groups):
172
+ labels.append(f"{min_val + interval * i:.2f}-{min_val + interval * (i + 1):.2f}")
173
+ # t = cls.from_dict({'value': group_counts}, xaxis=labels, title=title)
174
+
175
+ return cls.from_dict({'value': group_counts}, xaxis=labels, title=title)
176
+
177
+
178
+ class XlRadar(Radar):
179
+ """ 雷达图 """
180
+
181
+ def __init__(self, *args, **kwargs):
182
+ super().__init__(*args, **kwargs)
183
+ self.color_idx = 0
184
+
185
+ def add(
186
+ self,
187
+ series_name: str,
188
+ data: types.Sequence[types.Union[opts.RadarItem, dict]],
189
+ *,
190
+ label_opts=None,
191
+ color: types.Optional[str] = None,
192
+ linestyle_opts=None,
193
+ **kwargs
194
+ ):
195
+ """ 标准库(2.0.5版)的雷达图颜色渲染有问题,这里要增加一个修正过程 """
196
+ if label_opts is None:
197
+ label_opts = opts.LabelOpts(is_show=False)
198
+
199
+ if linestyle_opts is None:
200
+ linestyle_opts = opts.LineStyleOpts(color=self.colors[self.color_idx % len(self.colors)])
201
+ self.color_idx += 1
202
+ elif linestyle_opts.get('color') is None:
203
+ linestyle_opts.update(color=self.colors[self.color_idx % len(self.colors)])
204
+ self.color_idx += 1
205
+
206
+ if color is None:
207
+ color = linestyle_opts.get('color')
208
+
209
+ return super(XlRadar, self).add(series_name, data,
210
+ label_opts=label_opts,
211
+ color=color,
212
+ linestyle_opts=linestyle_opts,
213
+ **kwargs)
214
+
215
+
216
+ inject_members(XlBar, Bar)
217
+
218
+
219
+ def render_echart_html(title='Awesome-pyecharts', body=''):
220
+ from pyxllib.text.xmllib import get_jinja_template
221
+ return get_jinja_template('echart_base.html').render(title=title, body=body)
222
+
223
+
224
+ # 绘制帕累托累计图
225
+ def draw_pareto_chart(data, accuracy=0.1, *, title='帕累托累积权重', value_unit_type='K'):
226
+ from pyxllib.algo.stat import pareto_accumulate
227
+ pts, labels = pareto_accumulate(data, accuracy=accuracy, value_unit_type=value_unit_type)
228
+ x = Line()
229
+ x.add_series(title, pts, labels=labels, label={'position': 'right'})
230
+ x.set_global_opts(
231
+ # x轴末尾要故意撑大一些,不然有部分内容会显示不全
232
+ xaxis_opts=opts.AxisOpts(name='条目数', max_=int(float(f'{pts[-1][0] * 1.2:.2g}'))),
233
+ yaxis_opts=opts.AxisOpts(name='累积和')
234
+ )
235
+ return x
236
+
237
+
238
+ if __name__ == '__main__':
239
+ with TicToc(__name__):
240
+ pass
pyxllib/data/jsonlib.py CHANGED
@@ -1,89 +1,89 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- # @Author : 陈坤泽
4
- # @Email : 877362867@qq.com
5
- # @Date : 2024/04/01
6
-
7
- from collections import Counter
8
-
9
- from pyxllib.prog.pupil import check_install_package
10
-
11
- check_install_package('jmespath')
12
-
13
- import jmespath
14
-
15
-
16
- class JsonTool:
17
- @classmethod
18
- def find_paths_by_condition(cls, obj, condition, current_path=''):
19
- """
20
- 根据提供的条件递归搜索JSON对象,查找满足条件的路径。
21
- """
22
- if isinstance(obj, dict):
23
- for k, v in obj.items():
24
- new_path = f"{current_path}.{k}" if current_path else k
25
- if condition(k, v):
26
- yield new_path
27
- else:
28
- if isinstance(v, (dict, list)):
29
- yield from JsonTool.find_paths_by_condition(v, condition, new_path)
30
- elif isinstance(obj, list):
31
- for index, item in enumerate(obj):
32
- new_path = f"{current_path}[{index}]"
33
- if isinstance(item, (dict, list)):
34
- yield from JsonTool.find_paths_by_condition(item, condition, new_path)
35
-
36
- @classmethod
37
- def find_paths_with_key(cls, obj, key, current_path=''):
38
- """
39
- 查找包含指定键名的路径。
40
- """
41
- # 定义一个简单的条件函数,仅基于键名
42
- condition = lambda k, v: k == key
43
- return JsonTool.find_paths_by_condition(obj, condition, current_path)
44
-
45
-
46
- class JsonlTool:
47
- @classmethod
48
- def check_key_positions(cls, json_list, key):
49
- """
50
- 在JSON对象列表中统计每种包含指定键名的路径出现的次数。
51
-
52
- :param json_list: 包含多个JSON对象的列表。
53
- :param key: 要查找的键名。
54
- :return: 一个Counter对象,统计每种路径出现的次数。
55
- """
56
- paths_counter = Counter()
57
- for json_obj in json_list:
58
- # 使用JsonTool查找当前对象中包含指定键的路径
59
- paths = list(JsonTool.find_paths_with_key(json_obj, key))
60
- paths_counter.update(paths)
61
-
62
- return paths_counter
63
-
64
- @classmethod
65
- def check_path_values(cls, json_list, jmespath_expression, value_extractor=lambda x: x):
66
- """
67
- 根据提供的jmespath表达式,在JSON对象列表中直接统计表达式取值的次数。
68
- 支持自定义函数来获取要统计的键。
69
-
70
- :param json_list: 包含多个JSON对象的列表。
71
- :param jmespath_expression: 要应用的jmespath表达式。
72
- :param value_extractor: 一个函数,用于从jmespath.search的结果中提取要统计的值。
73
- :return: 一个Counter对象,统计提取值出现的次数。
74
- """
75
- values_counter = Counter()
76
- for json_obj in json_list:
77
-
78
- # 使用jmespath搜索当前对象
79
- result = jmespath.search(jmespath_expression, json_obj)
80
- # 使用自定义的value_extractor函数提取要统计的值
81
- extracted_values = value_extractor(result)
82
- if not isinstance(extracted_values, list):
83
- extracted_values = [extracted_values]
84
-
85
- for value in extracted_values:
86
- values_counter[value] += 1
87
-
88
- values_counter = Counter(dict(values_counter.most_common()))
89
- return values_counter
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # @Author : 陈坤泽
4
+ # @Email : 877362867@qq.com
5
+ # @Date : 2024/04/01
6
+
7
+ from collections import Counter
8
+
9
+ from pyxllib.prog.pupil import check_install_package
10
+
11
+ check_install_package('jmespath')
12
+
13
+ import jmespath
14
+
15
+
16
+ class JsonTool:
17
+ @classmethod
18
+ def find_paths_by_condition(cls, obj, condition, current_path=''):
19
+ """
20
+ 根据提供的条件递归搜索JSON对象,查找满足条件的路径。
21
+ """
22
+ if isinstance(obj, dict):
23
+ for k, v in obj.items():
24
+ new_path = f"{current_path}.{k}" if current_path else k
25
+ if condition(k, v):
26
+ yield new_path
27
+ else:
28
+ if isinstance(v, (dict, list)):
29
+ yield from JsonTool.find_paths_by_condition(v, condition, new_path)
30
+ elif isinstance(obj, list):
31
+ for index, item in enumerate(obj):
32
+ new_path = f"{current_path}[{index}]"
33
+ if isinstance(item, (dict, list)):
34
+ yield from JsonTool.find_paths_by_condition(item, condition, new_path)
35
+
36
+ @classmethod
37
+ def find_paths_with_key(cls, obj, key, current_path=''):
38
+ """
39
+ 查找包含指定键名的路径。
40
+ """
41
+ # 定义一个简单的条件函数,仅基于键名
42
+ condition = lambda k, v: k == key
43
+ return JsonTool.find_paths_by_condition(obj, condition, current_path)
44
+
45
+
46
+ class JsonlTool:
47
+ @classmethod
48
+ def check_key_positions(cls, json_list, key):
49
+ """
50
+ 在JSON对象列表中统计每种包含指定键名的路径出现的次数。
51
+
52
+ :param json_list: 包含多个JSON对象的列表。
53
+ :param key: 要查找的键名。
54
+ :return: 一个Counter对象,统计每种路径出现的次数。
55
+ """
56
+ paths_counter = Counter()
57
+ for json_obj in json_list:
58
+ # 使用JsonTool查找当前对象中包含指定键的路径
59
+ paths = list(JsonTool.find_paths_with_key(json_obj, key))
60
+ paths_counter.update(paths)
61
+
62
+ return paths_counter
63
+
64
+ @classmethod
65
+ def check_path_values(cls, json_list, jmespath_expression, value_extractor=lambda x: x):
66
+ """
67
+ 根据提供的jmespath表达式,在JSON对象列表中直接统计表达式取值的次数。
68
+ 支持自定义函数来获取要统计的键。
69
+
70
+ :param json_list: 包含多个JSON对象的列表。
71
+ :param jmespath_expression: 要应用的jmespath表达式。
72
+ :param value_extractor: 一个函数,用于从jmespath.search的结果中提取要统计的值。
73
+ :return: 一个Counter对象,统计提取值出现的次数。
74
+ """
75
+ values_counter = Counter()
76
+ for json_obj in json_list:
77
+
78
+ # 使用jmespath搜索当前对象
79
+ result = jmespath.search(jmespath_expression, json_obj)
80
+ # 使用自定义的value_extractor函数提取要统计的值
81
+ extracted_values = value_extractor(result)
82
+ if not isinstance(extracted_values, list):
83
+ extracted_values = [extracted_values]
84
+
85
+ for value in extracted_values:
86
+ values_counter[value] += 1
87
+
88
+ values_counter = Counter(dict(values_counter.most_common()))
89
+ return values_counter