Python分析一下双色球,中大奖指日可待!

简介: Python分析一下双色球,中大奖指日可待!

一、需求简介


之前偶然见到一位网友提出了关于双色球数据的分析需求,感觉颇有趣味,便着手操作了一番。如下为某双色球发布站的页面,可以看到每期会产生红/蓝两种颜色的数字,其中红球为 33 选 6,蓝球为 16 选 1,一共是从 49 个球中选 7 个。假如想对某一色号球下注,比如红1 球,要先分析一下该球以往的产出情况。


12.png


可以从以下 3 个方面来分析,以史明鉴,看看最新一期是否值得选取该球:


1、遗漏情况


统计遗漏 n 期后命中的次数,如上图:遗漏 1 期后中的次数有 2 次,遗漏 2 期后中的次数有 1 次,遗漏 5 期后中的次数有 2 次,遗漏 7 期后中的次数有 1 次。


13.png


2、连续重号情况


如图,连续重号 3 期的有 1 次。


14.png


3、重号前的遗漏情况


如图,重号前遗漏 2 期的有 1 次。



15.png


二、源数据


节选源数据如下,数据是以 html 表格形式储存的,<td> 标签中 class="yl01" 表示未命中,class="chartBall01" 表示命中红球,class="chartBall02" 表示命中蓝球(文末获取近 100 期数据样本)。


<tr>
    <td class="c_fbf5e3 bd_rt_a">2021090</td>
    <td class="yl01" style="font-size:xx-small">1</td>
    <td class="yl01" style="font-size:xx-small">1</td>
    <td class="yl01" style="font-size:xx-small">8</td>
    <td class="yl01" style="font-size:xx-small">2</td>
    <td class="chartBall01">05</td>
    <td class="chartBall01">06</td>
    <td class="yl01" style="font-size:xx-small">1</td>
    <td class="yl01" style="font-size:xx-small">4</td>
    <td class="yl01" style="font-size:xx-small">6</td>
    <td class="yl01" style="font-size:xx-small">4</td>
    <td class="yl01" style="font-size:xx-small">5</td>
    <td class="chartBall01">12</td>
    <td class="yl01" style="font-size:xx-small">1</td>
    <td class="chartBall01">14</td>
    <td class="yl01" style="font-size:xx-small">2</td>
    <td class="yl01" style="font-size:xx-small">2</td>
    <td class="yl01" style="font-size:xx-small">13</td>
    <td class="yl01" style="font-size:xx-small">9</td>
    <td class="yl01" style="font-size:xx-small">2</td>
    <td class="yl01" style="font-size:xx-small">5</td>
    <td class="yl01" style="font-size:xx-small">6</td>
    <td class="yl01" style="font-size:xx-small">9</td>
    <td class="yl01" style="font-size:xx-small">1</td>
    <td class="yl01" style="font-size:xx-small">1</td>
    <td class="yl01" style="font-size:xx-small">7</td>
    <td class="yl01" style="font-size:xx-small">2</td>
    <td class="chartBall01">27</td>
    <td class="chartBall01">28</td>
    <td class="yl01" style="font-size:xx-small">4</td>
    <td class="yl01" style="font-size:xx-small">13</td>
    <td class="yl01" style="font-size:xx-small">12</td>
    <td class="yl01" style="font-size:xx-small">8</td>
    <td class="yl01" style="font-size:xx-small">7</td>
    <td class="v_line"></td>
    <td class="yl01" style="font-size:xx-small">4</td>
    <td class="yl01" style="font-size:xx-small">5</td>
    <td class="yl01" style="font-size:xx-small">42</td>
    <td class="yl01" style="font-size:xx-small">3</td>
    <td class="yl01" style="font-size:xx-small">8</td>
    <td class="yl01" style="font-size:xx-small">2</td>
    <td class="yl01" style="font-size:xx-small">16</td>
    <td class="chartBall02">08</td>
    <td class="yl01" style="font-size:xx-small">10</td>
    <td class="yl01" style="font-size:xx-small">13</td>
    <td class="yl01" style="font-size:xx-small">54</td>
    <td class="yl01" style="font-size:xx-small">1</td>
    <td class="yl01" style="font-size:xx-small">11</td>
    <td class="yl01" style="font-size:xx-small">31</td>
    <td class="yl01" style="font-size:xx-small">18</td>
    <td class="yl01" style="font-size:xx-small">25</td>
</tr>
<tr>
    <td class="c_fbf5e3 bd_rt_a">2021091</td>
    <td class="yl01" style="font-size:xx-small">2</td>
    <td class="yl01" style="font-size:xx-small">2</td>
    <td class="yl01" style="font-size:xx-small">9</td>
    <td class="chartBall01">04</td>
    <td class="yl01" style="font-size:xx-small">1</td>
    <td class="chartBall01">06</td>
    <td class="yl01" style="font-size:xx-small">2</td>
    <td class="yl01" style="font-size:xx-small">5</td>
    <td class="yl01" style="font-size:xx-small">7</td>
    <td class="yl01" style="font-size:xx-small">5</td>
    <td class="yl01" style="font-size:xx-small">6</td>
    <td class="yl01" style="font-size:xx-small">1</td>
    <td class="yl01" style="font-size:xx-small">2</td>
    <td class="yl01" style="font-size:xx-small">1</td>
    <td class="yl01" style="font-size:xx-small">3</td>
    <td class="chartBall01">16</td>
    <td class="yl01" style="font-size:xx-small">14</td>
    <td class="yl01" style="font-size:xx-small">10</td>
    <td class="yl01" style="font-size:xx-small">3</td>
    <td class="yl01" style="font-size:xx-small">6</td>
    <td class="yl01" style="font-size:xx-small">7</td>
    <td class="yl01" style="font-size:xx-small">10</td>
    <td class="yl01" style="font-size:xx-small">2</td>
    <td class="chartBall01">24</td>
    <td class="yl01" style="font-size:xx-small">8</td>
    <td class="chartBall01">26</td>
    <td class="yl01" style="font-size:xx-small">1</td>
    <td class="yl01" style="font-size:xx-small">1</td>
    <td class="yl01" style="font-size:xx-small">5</td>
    <td class="yl01" style="font-size:xx-small">14</td>
    <td class="yl01" style="font-size:xx-small">13</td>
    <td class="yl01" style="font-size:xx-small">9</td>
    <td class="chartBall01">33</td>
    <td class="v_line"></td>
    <td class="yl01" style="font-size:xx-small">5</td>
    <td class="yl01" style="font-size:xx-small">6</td>
    <td class="yl01" style="font-size:xx-small">43</td>
    <td class="yl01" style="font-size:xx-small">4</td>
    <td class="yl01" style="font-size:xx-small">9</td>
    <td class="yl01" style="font-size:xx-small">3</td>
    <td class="yl01" style="font-size:xx-small">17</td>
    <td class="yl01" style="font-size:xx-small">1</td>
    <td class="yl01" style="font-size:xx-small">11</td>
    <td class="yl01" style="font-size:xx-small">14</td>
    <td class="yl01" style="font-size:xx-small">55</td>
    <td class="yl01" style="font-size:xx-small">2</td>
    <td class="yl01" style="font-size:xx-small">12</td>
    <td class="yl01" style="font-size:xx-small">32</td>
    <td class="yl01" style="font-size:xx-small">19</td>
    <td class="chartBall02">16</td>
</tr>


三、解析实现


1、数据结构


为了便于表示球的命中与颜色、数值,我们可以按以下规则映射:


微信图片_20220617142527.png


那么先用美丽汤把需要的内容捞出来,把所有 <td> 标签中表示名字与色号的内容取出,按上述规则映射表示。


soup = BeautifulSoup(res_table, "html.parser")
item_lst = []
for td in soup.find_all('td'):
  cls = td['class'][0]
  num = td.string
  if cls in ['yl01', 'chartBall01', 'chartBall02']:
      item_lst.append('-'.join([cls, num]))
print(item_lst[:10])


输出前 10 个预览如下:


['yl01-3', 'yl01-5', 'chartBall01-03', 'yl01-5', 'yl01-1', 'yl01-5', 'chartBall01-07', 'yl01-9', 'yl01-6', 'yl01-6']


但这仅仅是一个超长列表,在此基础上处理起来还找不到头绪,至少要转变成和网页上结构一致的矩阵才好理解吧,那么可以想到利用 numpy 矩阵。先是用 np.array 将普通列表转为 numpy 数组,再利用 reshape 将一维数组转为二维数组,即 100 期 X 49 个球的矩阵。


array = np.array(item_lst).reshape(100, 49)


如图,numpy 矩阵的每一行与原页面结构对应。


16.png


但我们想要进行的是纵向比较分析,比较各期之间的关系,所以还需要再对矩阵进行行列转置。


array_T = array.T  # 矩阵转置,一个元素对应一列


17.png


此时,array_T 中的每一个元素即表示某一色号的近 100 期情况。如果想看红1 球,则是 array_T[0];如果想看红2 球,则是 array_T[1];如果想看蓝1 球,则是 array_T[33](因为红球总共有 33 个,故第一个蓝球列的索引为 33)。为了便于选球,我们可以写一个映射方法:


def trans_col(txt):# 翻译列索引号,如红1=0,红33=32,蓝1=33,蓝16=48
    if"红"in txt:
        col = int(txt.replace('红', '')) - 1
    else:
        col = int(txt.replace('蓝', '')) + 32
    return col

接下来就可以正式开始实现统计分析的需求啦!


2、遗漏统计


将转置矩阵和指定色号球所在列传入,获取该列后加入一个结束标记,因至少要出现 1 次未命中 +1 次命中才判定为遗漏 1 期,所以从该列的第二项数据开始判断,若其不等于前一项的值,且当前项为命中,则记录前一项的值(遗漏期数)。之后将记录列表中的表示遗漏的标记 yl01 去除,仅保留期数。


def fun_miss(array, col):# 统计该列中遗漏后命中的次数
    line = array[col].tolist()
    order_grp = []
    for i, v in enumerate(line):
        if i > 0:
            if v != line[i - 1] and'chart'in v:
                order_grp.append(line[i - 1])
    order_grp = [i.replace('yl01-', '') for i in order_grp]
    c = dict(Counter(order_grp))
    result = sorted(c.items(), key=lambda x: int(x[0]))
    for i in result:
        print(f"遗漏{i[0]}期后中的次数有{i[1]}次")
fun_miss(array_T, trans_col("红1"))  # 执行



18.png


统计排序后输出如下:

遗漏1期后中的次数有4次 遗漏2期后中的次数有2次 遗漏3期后中的次数有3次 遗漏5期后中的次数有2次 遗漏7期后中的次数有2次 遗漏8期后中的次数有1次 遗漏9期后中的次数有2次 遗漏13期后中的次数有1次


3、连续重号统计


与遗漏统计相同,传入两个参数,先确定要选取的色号列。当前项等于前一项,且当前项为命中时表示重号,连续重号时 count 计数 +1,当出现不满足重号条件时表示连续重号中断,记录连续次数,并将计数清零,待下一轮重号出现时重新计数。


def fun_repeat(array, col):# 统计该列中的重号次数
    line = array[col].tolist()
    count_grp = []
    count = 0
    for i, v in enumerate(line):
        if i > 0:
            if v == line[i-1] and'chart'in v:
                count += 1
            elif count > 0:
                count_grp.append(count)
                count = 0
    c = dict(Counter(count_grp))
    result = sorted(c.items(), key=lambda x: x[0])
    for i in result:
        print(f"连续重号{i[0]}次的有{i[1]}次")
fun_repeat(wt, trans_col("红2"))  # 执行



19.png


统计排序后输出如下:

连续重号1次的有1次 连续重号2次的有1次


4、重号前的遗漏统计


因要出现重号+遗漏才算入,所以至少从第三项数据开始判定。


def fun_return(array, col):# 统计该列中重号前的遗漏次数
    line = array[col].tolist()
    order_grp = []
    for i, v in enumerate(line):
        if i > 1:
            if v == line[i - 1] and v != line[i - 2] and'chart'in v:
                order_grp.append(line[i - 2])
    order_grp = [i.replace('yl01-', '') for i in order_grp]
    c = dict(Counter(order_grp))
    result = sorted(c.items(), key=lambda x: int(x[0]))
    for i in result:
        print(f"重号前遗漏{i[0]}期的有{i[1]}次")
fun_return(wt, trans_col("红1"))  # 执行



19.png


统计排序后输出如下:

重号前遗漏2期的有1次


四、小结


点击下方[在看],即可找志斌领取源数据和完整代码哈~

相关文章
|
1月前
|
机器学习/深度学习 算法 搜索推荐
从理论到实践,Python算法复杂度分析一站式教程,助你轻松驾驭大数据挑战!
【10月更文挑战第4天】在大数据时代,算法效率至关重要。本文从理论入手,介绍时间复杂度和空间复杂度两个核心概念,并通过冒泡排序和快速排序的Python实现详细分析其复杂度。冒泡排序的时间复杂度为O(n^2),空间复杂度为O(1);快速排序平均时间复杂度为O(n log n),空间复杂度为O(log n)。文章还介绍了算法选择、分而治之及空间换时间等优化策略,帮助你在大数据挑战中游刃有余。
60 4
|
11天前
|
数据采集 缓存 定位技术
网络延迟对Python爬虫速度的影响分析
网络延迟对Python爬虫速度的影响分析
|
28天前
|
数据采集 JSON 数据处理
抓取和分析JSON数据:使用Python构建数据处理管道
在大数据时代,电商网站如亚马逊、京东等成为数据采集的重要来源。本文介绍如何使用Python结合代理IP、多线程等技术,高效、隐秘地抓取并处理电商网站的JSON数据。通过爬虫代理服务,模拟真实用户行为,提升抓取效率和稳定性。示例代码展示了如何抓取亚马逊商品信息并进行解析。
抓取和分析JSON数据:使用Python构建数据处理管道
|
13天前
|
数据采集 存储 JSON
Python爬虫开发中的分析与方案制定
Python爬虫开发中的分析与方案制定
|
20天前
|
数据可视化 开发者 Python
Python GUI开发:Tkinter与PyQt的实战应用与对比分析
【10月更文挑战第26天】本文介绍了Python中两种常用的GUI工具包——Tkinter和PyQt。Tkinter内置于Python标准库,适合初学者快速上手,提供基本的GUI组件和方法。PyQt基于Qt库,功能强大且灵活,适用于创建复杂的GUI应用程序。通过实战示例和对比分析,帮助开发者选择合适的工具包以满足项目需求。
69 7
|
1月前
|
数据可视化 算法 Python
基于OpenFOAM和Python的流场动态模态分解:从数据提取到POD-DMD分析
本文介绍了如何利用Python脚本结合动态模态分解(DMD)技术,分析从OpenFOAM模拟中提取的二维切片数据,以深入理解流体动力学现象。通过PyVista库处理VTK格式的模拟数据,进行POD和DMD分析,揭示流场中的主要能量结构及动态特征。此方法为研究复杂流动系统提供了有力工具。
72 2
基于OpenFOAM和Python的流场动态模态分解:从数据提取到POD-DMD分析
|
19天前
|
存储 数据处理 Python
Python科学计算:NumPy与SciPy的高效数据处理与分析
【10月更文挑战第27天】在科学计算和数据分析领域,Python凭借简洁的语法和强大的库支持广受欢迎。NumPy和SciPy作为Python科学计算的两大基石,提供了高效的数据处理和分析工具。NumPy的核心功能是N维数组对象(ndarray),支持高效的大型数据集操作;SciPy则在此基础上提供了线性代数、信号处理、优化和统计分析等多种科学计算工具。结合使用NumPy和SciPy,可以显著提升数据处理和分析的效率,使Python成为科学计算和数据分析的首选语言。
28 3
|
20天前
|
存储 机器学习/深度学习 算法
Python科学计算:NumPy与SciPy的高效数据处理与分析
【10月更文挑战第26天】NumPy和SciPy是Python科学计算领域的两大核心库。NumPy提供高效的多维数组对象和丰富的数学函数,而SciPy则在此基础上提供了更多高级的科学计算功能,如数值积分、优化和统计等。两者结合使Python在科学计算中具有极高的效率和广泛的应用。
38 2
|
25天前
|
数据采集 机器学习/深度学习 搜索推荐
Python自动化:关键词密度分析与搜索引擎优化
Python自动化:关键词密度分析与搜索引擎优化
|
26天前
|
数据可视化 算法 JavaScript
基于图论的时间序列数据平稳性与连通性分析:利用图形、数学和 Python 揭示时间序列数据中的隐藏模式
本文探讨了如何利用图论分析时间序列数据的平稳性和连通性。通过将时间序列数据转换为图结构,计算片段间的相似性,并构建连通图,可以揭示数据中的隐藏模式。文章介绍了平稳性的概念,提出了基于图的平稳性度量,并展示了图分区在可视化平稳性中的应用。此外,还模拟了不同平稳性和非平稳性程度的信号,分析了图度量的变化,为时间序列数据分析提供了新视角。
54 0
基于图论的时间序列数据平稳性与连通性分析:利用图形、数学和 Python 揭示时间序列数据中的隐藏模式