Python 来算算一线城市的二手房价格指数相关性

Python中有很多方法计算相关性,scipy中有自带的分析工具,pandas里也有非常方便的多变量相关性分析。我们今天就讲讲这两个工具的用法。

1.数据收集

本文北上广深的数据采集自东方财富网,以二手房价格指数为例:

数据从2011年1月1日开始,每个数据点是当时一个月的价格指数,采集方法是用开发者工具找到请求发回来的JSON数据,方法如下:

数据如下(2011/1/1-2019/10/1):

# 北京:
bj = [100.3,100.4,99.9,100.1,99.8,99.9,100.1,100,99.6,99.5,99.3,99.2,99.1,99.8,100.2,100.4,99.9,100.2,100.3,100.3,100.1,100,100.3,101,101,102.2,103.1,102,101.7,101.3,101.4,101.2,101.3,101.1,101.2,100.6,99.9,100,100.2,99.8,99.1,98.7,99.2,99.1,98.6,100.3,100.7,100.2,100,99.9,100.5,102.1,104.3,102.3,102.6,102,101.4,101.1,101.4,101.7,102.3,103.2,106.3,103.7,102.3,101.4,101.6,103.9,105.7,101.1,100.2,100.2,100.8,101.3,102.2,100,99.1,98.9,99.2,99.1,99.4,99.5,99.5,99.6,99.4,99.5,99.8,99.9,100.3,100.1,100.4,100,99.8,99.8,99.4,99.8,99.9,100.2,100.4,100.6,100,100,99.7,99.6,99.5,99.4]
# 广州:
gz = [101.2,100.6,99.5,101,99.8,100.1,100.2,100.7,100.6,99.5,99.2,99.6,99.6,99.6,99.8,99.6,99.9,100.5,100.7,100.9,100.6,100.4,100.5,100.5,100.4,101.7,101.5,100.7,101.1,100.9,101,101,100.4,101,101.2,100.6,101,100.3,100.2,100.7,100.1,99.7,98.9,98.6,98.7,100,100,100.2,99.8,99.7,100,101.1,102.3,101.8,101.3,101,101.2,101.1,100.7,101,101.3,101.2,103.5,102.6,101.9,101.6,101.4,102.8,103.3,101.6,100.8,101.3,101.6,102.7,103.3,101,100.5,100.8,100.1,100,100.2,99.7,100.1,99.6,99.9,100.2,100.2,100.5,101,100.3,100.3,100.6,100.2,99.8,99.7,99.6,99.7,99.8,99.5,99.6,99.7,100,100.4,100,99.7,99.9]
# 上海: 
sh = [100.5,100.4,100.4,100.6,100.2,100.2,100.3,100.1,100.1,99.8,99.5,99.6,99.3,99.7,99.5,100.1,100.3,100.2,100.2,100.3,100.2,100.2,100.2,100.4,100.8,101.6,102.6,101.3,100.9,101.1,100.8,100.8,101,100.9,100.7,100.5,100.1,100.6,100.2,100,99.8,99.3,99.1,99.3,99.2,100,100,100.4,100.3,100.1,100,100.6,102.2,101.2,101.6,101.1,101,100.8,101,101.2,102.7,105.3,106.2,102.5,101.4,102.2,102,103.7,103.4,100.3,99.8,99.5,99.6,100.2,100.7,100.8,100,99.9,99.6,99.8,99.9,100.3,99.7,99.9,100.1,99.6,99.4,99.8,99.7,99.7,99.9,99.9,99.8,99.8,99.9,99.7,100,99.9,100.3,100.5,100.1,99.9,100.4,100,100.6,99.8]
# 深圳:
sz = [100.6,102.6,100.6,100.5,100.3,100,99.5,100,99.8,100,99.2,99.6,99.2,100,100.1,100,100,100.2,100.2,100.1,100.1,100.4,100.3,100.6,100.5,101.4,102.3,101.1,101,101.3,101,101.6,101.3,100.9,100.8,100.7,100.8,100.8,101.1,100.1,100.2,99.4,99.4,99.5,99.3,100,100.4,100.7,100.6,100.3,100.5,102.4,106.3,106.9,105.3,104.4,103.3,101,101.9,103.3,105.7,103.3,104.7,99.6,100,100.8,101.8,102,101.8,99.4,99.3,99.8,99.9,99.3,100.3,100.8,100.3,99.7,100.6,99.8,99.9,100.4,100.1,100.4,100.9,101.3,100.7,100.2,100.8,100.3,100.6,101.1,100,99.4,99.8,99.7,99.7,100.5,100.7,101.1,100,99.9,100.7,100.2,101.3,101] 

2.准备工作

首先,你要确保你的电脑安装了Python,如果没有可以看这篇文章:超详细安装Python指南

然后,打开CMD(开始-运行-cmd),或者Terminal(macOS) 输入以下指令安装scipy和pandas.

pip install scipy 
pip install pandas

3.编写代码

3.1 scipy计算相关性

scipy计算相关性其实非常简单,引入包的stats模块:

import scipy.stats as stats 

然后调用函数进行计算:

# 计算广州和深圳二手房价格指数相关性
print(stats.pearsonr(gz, sz))

结果如下:

F:\push\20191130>python 1.py
(0.4673289851643741, 4.4100775485723706e-07)

什么?!!广州和深圳的二手房价格指数相关性竟然才0.46?那其他一线城市和深圳对比呢?

不过,stats麻烦的地方就在于,它一次只能对比两个值,不能一次性两两对比四个一线城市,不过,有个模块可以。

3.2 pandas一次性两两对比计算相关性

首先引入pandas:

import pandas as pd

创建DataFrame存放四个数据:

df = pd.DataFrame()
df['北京'] = bj
df['上海'] = sh
df['广州'] = gz
df['深圳'] = sz 

最后相关性计算:

print(df.corr()) 

来看看结果:

wow,看来深圳的二手房价还真是与众不同,不过从下面这个图看,确实,深圳的二手房价格和北京的二手房价格已经出现了背离的情况。

个人认为,这个背离和最近的一系列政策及香港局势有关,但当前严峻的金融形势下,不会持续太久。

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Blender, 用Python绘制宇宙飞船的3D建模软件

见过用Python进行3D建模操作的么?下面给你演示一下:

强不强?这就是Blender,一款能用Python进行建模的软件。

Blender是一个免费的开源3D计算机图形软件工具集,用于创建动画电影视觉效果,艺术品,3D打印模型,动态图形,交互式3D应用程序和计算机游戏

不仅如此,它还提供了一个Python与Blender交互的API: https://docs.blender.org/api/2.81/ ,使Python进行3D建模成为一种可能。

下面介绍一下这个宇宙飞船项目。这是一个比赛作品,作者用它参与了reddit的一个2016年6月的挑战赛。实现的原理并不复杂,就是从一个立方体开始建造船体,利用随机数增加船体的不确定性。然后慢慢地往船体增加细节,比如引擎、天线、炮塔、照明灯等等。

项目地址: https://github.com/a1studmuffin/SpaceshipGenerator

快来生成你的宇宙飞船

要想运行这个项目,你需要做如下准备:

1. 安装Blender 2.76以上:
https://www.blender.org/download/

2. 下载作者的生成代码(也就是已经和Blender做好API联调的代码)。
如果你访问不了Github, 可在公众号后台回复 宇宙飞船 下载这些代码。

3. 将下载好的代码( add_mesh_SpaceshipGenerator.zip, 以压缩包的形式)载入到blender中:

3.1 点击菜单栏里的 Edit — 选择Preferences.

3.2 选择左侧的Add-ons,然后点击install,选择刚刚下载下来的压缩包。

3.3 载入后记得勾选插件。

4. 使用快捷键shift+F5进入3D视图

5. 使用快捷键shift+A,这时候鼠标右键会弹出选项,在mesh中选择 Spaceship即可生成你的宇宙飞船!

怎么样,够不够帅?记得自己实践一下生成一个哦!

自己用Python进行DIY

如果你想自己再进行一下DIY,让飞船变得更帅气,那也是可以的!把下载下来的压缩包解压,里面会有一个文件叫spaceship_generator.py的,这个就是主要的模型生成代码。你能在里面看到作者的许多参数设置,稍微修改一下会有惊喜哦!

你也可以阅读完作者的这份源代码(也不多,就800行),自己学着做一个有别于宇宙飞船的3D模型!

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

快来用Python制作只属于你和ta的聊天渠道吧

是否担心微信的数据流会被监视?是否担心你和ta聊天的小秘密会被保存到某个数据里?没关系,现在我们可以用Python做一个只属于你和ta的聊天渠道,来解除你们心中的担忧。

1.原理简介

在我们今天的教程中,将用到即时通讯的概念,即时通讯允许两人或多人同时使用网络传递文字信息、文字、语音等。即时通讯一般都基于socket连接,socket连接可用于发送或接受数据,一般的组合形式是IP+端口号

也就是说,在我们的例子中,聊天的双方,由一方要承担“服务器 ” 的责任,维持一个socket服务器,等待连接进入;另一方则是“客户端”,在服务器端维持等待状态时即可发送请求,建立连接。

当你和ta想进入“小黑屋 ” 里聊天的时候,只有有一方充当服务器,另一方充当客户端即可,作为“服务器端 ” 的那个人,在微信中将IP和端口号告诉对方,即可构建连接,在小黑屋里聊天,这个小黑屋里的数据不会被任何数据保留(除非你自己做了一个保存的数据)。

2.代码编写

好了,基本原理我们已经讲清楚了。不过,在开始教程之前,你得先安装好了Python,如果还没有安装,可以看这篇文章:https://pythondict.com/python-tutorials/how-to-install-python/

2.1 服务器端

聊天的时候,我们有时候会遇到双方同时发消息的情况。这种聊天方式就叫全双工聊天方式:“服务器”可向“客户端”发送消息,“客户端”也可向“服务端”发送消息,而且允许同时发送消息。

服务器端怎么实现全双工的聊天方式呢?其实很简单,只要用多线程就行了,主线程用于接收客户端的连接,连接成功后新建两个线程:一个用于发送消息,一个用于接收消息:

首先,建立socket服务器:

import socket
import traceback
# 设定ip和端口号
host = ''
port = 51423 
# 建立socket服务器
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((host,port))
s.listen() 
while True:
    # 等待连接
    try:
        clientsock, clientaddr = s.accept()
    except KeyboardInterrupt:
        raise
    except:
        traceback.print_exc()
        continue 

其中,AF_INET指的是用IPv4进行通信,而SOCK_STREAM指的是TCP协议。端口号你可以随意设定,服务器端的IP地址默认为空即可。

在while循环中不断等待用户的连接。如果有用户连接成功了,我们将进入下一步,分别建立发送和接受线程:

# 建立接收线程
t = _thread.start_new_thread(processRecv, (clientsock,))

# 建立发送线程
r = _thread.start_new_thread(processSend, (clientsock,)) 

clientsock就是我们得到的socket连接,processRecv和processSend分别用于处理接受信息和处理发送信息:

import _thread 
def processRecv(clientsock):
    """
    接受消息
        :param clientsock: 客户端的socket连接
    """
    while True:
        data = clientsock.recv(4096)
        if not len(data):
            break
        print (data.decode('utf-8'))
    clientsock.close()

def processSend(clientsock):
    """
    发送消息
        :param clientsock: 客户端的socket连接
    """
    while True:
        data = input("> ")
        data = data
        clientsock.sendall(data.encode('utf-8'))
    clientsock.close() 

有个小细节要注意,socket连接的sendall函数只支持bytes类型的数据,所以我们要encode(‘utf-8’)。

服务端的所有代码就这样,没错,就是这么简单。

2.2 客户端

客户端则更简单,主线程本身设定为接受消息,那么我们只需要多一个线程用于发送消息即可。客户端的全部代码如下:

#-*-coding:utf-8-*-

import _thread
import sys
from socket import *

def send_message(tcpCliSock):
    """
    发送信息
        :param tcpCliSock: 与服务端的socket连接
    """
    while True:
        message = input('> ')
        if not message:
            break
        tcpCliSock.send(message.encode('utf-8'))

    tcpCliSock.close()

if(len(sys.argv) < 3):
    HOST = 'localhost'
    PORT = 51423
else:
    HOST = sys.argv[1]
    PORT = int(sys.argv[2])

BUFSIZ = 1024
ADDR = (HOST,PORT)

tcpCliSock = socket(AF_INET,SOCK_STREAM)
tcpCliSock.connect(ADDR)

# 建立发送消息的线程
s = _thread.start_new_thread(send_message, (tcpCliSock,))

while True:
    rdata = tcpCliSock.recv(BUFSIZ)
    if not rdata:
        break
    print (rdata.decode('utf-8'))
    
tcpCliSock.close() 

其中,HOST部分填写对方的IP,PORT部分填写端口号。sys.argv用于通过参数输入这两个值,比如我们将客户端文件命名为:client.py, 在cmd中输入:

python client.py 127.0.0.1 51423

能直接传入参数执行脚本,除此之外,其他部分和服务端其实差不多。注意把接受到的数据decode一下(因为我们发的时候encode了)。

3. 改进

实际上,这份代码虽然可以用,但是还是存在许多问题的。比如在你们聊天的时候,突然又有一个人向服务端发送连接请求怎么办?这时候我们需要在服务端加一份拥有验证的代码,要求对方输入聊天室密码后才可建立连接。

这个密码必须是你们双方才知道的密码,任何通过第三方工具传播密码的行为都是不可靠和不安全的。这样才可以防止第三者的偷听。增加一个密码功能其实也不难,这部分交给大家自己去实现啦!

本文完整源代码下载请在公众号后台回复:聊天渠道

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 超简单3行代码提取音乐高潮(批量提取实战教程)

有些时候,为了设定手机铃声或者发抖音视频,我们会耗费大量时间在剪辑音乐高潮部分上。那么这个音乐高潮的提取能不能自动化呢?当然可以。

1.原理简介

不知道大家有没有这样的体会,大部分时候,歌曲的高潮部分通常是重复次数最多的部分。因此我们可以根据这一个特征,提出我们的算法

1.遍历整首歌曲。

2.将选定长度的部分与其他部分比较并计算相似度,以查看是否重复。

3.寻找重复次数较大、且间隔长的片段。

2.代码编写

为了避免造轮子,我们找到了别人已经做过的类似的项目:

https://github.com/vivjay30/pychorus

我们只需要分析这个源代码中最核心的部分,即求相似区段的源代码:

def compute_similarity_matrix_slow(self, chroma):
    """
    虽然慢,但是直接的方法来计算区段相似矩阵
    """
    num_samples = chroma.shape[1]
    time_time_similarity = np.zeros((num_samples, num_samples))
    for i in range(num_samples):
        for j in range(num_samples):
        # 检测每一段的相似度
            time_time_similarity[i, j] = 1 - (np.linalg.norm(chroma[:, i] - chroma[:, j]) / sqrt(12))
    return time_time_similarity 

可以看到,这部分代码就是做了我们算法的第二步,进行了片段与片段之间的相似度计算。检测时用到的相似函数是这样的:

这主要是因为歌曲由12个基本音符的帧的集合而组成,v1和v2是任意两段音乐的音符矢量,如果说两段音乐非常相似,那么右边的式子将接近于0. 如果说 1-右边的式子 得分非常高,则说明两段音乐非常相似

下面我们看看怎么使用这个项目求音乐高潮部分,其实非常简单。

2.1 安装所需要的项目

你可以通过pip安装该项目,如果你还没有安装好Python相关环境,建议阅读这篇文章:Python安装

pip install pychorus

2.2 编写代码

实际上,这个包用起来可是相当简单,如果我们只是想单纯提取歌曲高潮部分:

from pychorus import find_and_output_chorus
chorus_start_sec = find_and_output_chorus("你的音乐文件", "输出高潮部分文件", 要多少秒的高潮部分) 

没错,两行代码就解决了。下面让我们检验一下效果。

3.效果检验

以《孤芳自赏》 为例,让我们试试这个提取器的功力。

原曲:

https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2019/11/2019112414210248.mp3

编写代码:

# 提取音乐高潮部分
from pychorus import find_and_output_chorus
chorus_start_sec = find_and_output_chorus("孤芳自赏.mp3", "孤芳自赏_high.wav", 40)

效果如下:

https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2019/11/2019112414230277.wav

非常优秀!提取了我心目中想要的部分。大家也可以根据我们今天的教程,试着提取一下自己喜欢的音乐的高潮部分哦!

4.批量提取

刚刚,只是完成了单首歌曲的高潮提取,如果你想提取整个文件夹下的音乐的高潮部分,可以这样做:

# Python 实用宝典
# 提取音乐高潮部分
# 2020/06/11

import os
import sys
from pychorus import find_and_output_chorus


def extract_all_file(files_path):
    """
    批量提取音乐高潮

    Args:
        files_path (str): 文件夹路径
    """

    # 文件夹路径
    modpath = os.path.dirname(os.path.abspath(sys.argv[0]))

    for filepath in os.listdir(files_path):

        # 路径处理
        datapath = os.path.join(modpath, files_path + filepath)

        # output文件夹是否存在
        targets = f"{modpath}\\output\\"
        if not os.path.exists(targets):
            os.makedirs(targets)

        # 提取音乐高潮至当前output文件夹下
        find_and_output_chorus(
            datapath, f"{targets}{filepath.split('.')[0]}_high.wav", 40
        )


extract_all_file("F:\\push\\20200611\\music\\")

这样就可以实现批量提取音乐高潮的功能。

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!

音乐相关教程:

Python 批量下载网易云音乐歌单

Python 制作音乐高潮副歌提取器

Python Django快速开发音乐高潮提取网(1)

Python Django快速开发音乐高潮提取网(2)

Python Django快速开发音乐高潮提取网(3)

Python 超方便超快速剪辑音乐

Python 提取音乐频谱并可视化


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 预测广东省2019年12月猪肉价格

前段时间我们用回归的方法预测了天猫的2019年销售额:《Python 多项式预测2019年天猫销售额》以及《人口出生率预测》 。今天我们将使用Facebook的“先知”模型来预测12月的猪价。

Python实用宝典其实已经用过“先知”模型,大家可以阅读这篇文章:《Python使用”先知”预测公众号未来的粉丝量》,当时预测公众号的粉丝在一个月后最多增长到547人,实际增长到了542人,预测地相当准确,而且是在我的宣传模式做了一些改变的情况下的效果,可见这个模型能够很好地处理一些异常变化。

今天我们将使用先知模型预测2019年12月广东省的猪肉价格,源代码和数据你都能通过关注文章最下方的公众号,后台回复:猪价预测 获得。本实验仅供参考。

1.准备数据

在猪价系统网站上利用开发者工具获得过去一年广东省的猪肉价格保存为json格式:
https://zhujia.zhuwang.cc/areapriceinfo-440000.shtml

部分数据如下:

实际上我认为,就猪价这样的对象,拿一年的数据是远远不够的,但是实在找不到前几年的数据。作为一次实验,我暂时以过去一年的数据作为训练集,如果你想要更精准地预测价格,建议至少找3年的数据。

2.数据预测

以下教程默认你已经安装好了Python并可以在CMD或Terminal中使用pip,如果没有请看这篇文章:安装python

2.1 安装 “先知” prophet

Prophet这个包真是一言难尽,如果你按照官方的教程来进行安装, 你会发现啥也安装不上(我吐了)。这里给大家介绍我的安装方法,避免你们走弯路:

第一步,我们需要安装fbprophet的依赖PyStan:

pip install pystan

第二步,使用conda命令安装(需要安装anaconda, 搜anaconda官网安装即可):

conda install -c conda-forge fbprophet

2.2 编写预测代码

首先,利用开发者工具弄下来的数据缺少日期,我们需要获得过去365天的日期,并与原数据对应上:

# 获得2019-11-20过去365天的数据
days = []
today = datetime.date.today()
for i in range(0,366,1):
    daybeforetoday = today + datetime.timedelta(days=-i)
    days.append(daybeforetoday.strftime('%Y-%m-%d'))
days = list(reversed(days))
print(days) 

然后我们将猪价提取出来,并将日期和猪价转换为pandas的DataFrame格式:

f = open('./data_20191120.json', 'r', encoding='utf-8')
json_data = json.load(f)
f.close()
# 提取猪价
list_number = json_data['pigprice']
print(len(list_number), len(days))
# prophet模型预测前需要将日期列设为ds,预测的值设为y
df = pd.DataFrame({'y':list_number, 'ds':days})
print(len(df), len(days))

最后,调用先知模型进行预测,这里我们只预测30天,所以periods设为了30:

from fbprophet import Prophet

# 调用"先知"生成对象
m = Prophet()

# 使用"先知对象"进行预测
m.fit(df)

# 获得未来30天的数据
future = m.make_future_dataframe(periods=30)

forecast = m.predict(future)
print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail())  

结果如下:

根据过去一年(可能不够)的猪肉价格数据,预测到在下个月的今天,猪肉将会上涨到49元/公斤左右的价格。由于数据量实在是太少了,检测不出每一年的猪肉波动性,因此这个预测得到的数据我估计误差比较大,但是大家只需要知道先知模型的使用方法,本文就值了。

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 人口出生率数据预测及可视化

上次我们用多项式回归预测了天猫的2019年销售额:《Python 多项式预测2019年天猫销售额》。今天的文章同样教大家怎么进行预测,不过对象换成2019年人口出生率。

今天我们将使用多项式回归模型预测2019年的中国人口出生率。

1.准备

在中华人民共和国国家统计局官方网站上下载过去20年的人口出生率数据:http://data.stats.gov.cn/easyquery.htm?cn=C01

数据如下,我们仅取人口出生率作为我们的数据集。

2.数据预测

以下教程默认你已经安装好了Python并可以在CMD或Terminal中使用pip,如果没有请看这篇文章:安装python,同上一节预测2019年天猫销售额一样,没有太多的改变,但是我们需要找到最合适的曲线,而不是一上来就用三元回归曲线:

2.1 数据预处理

# 数据集
datasets_X = [1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018]
datasets_Y = [14.64, 14.03, 13.38, 12.86, 12.41, 12.29, 12.4, 12.09, 12.1, 12.14, 11.95, 11.9, 11.93, 12.1, 12.08, 12.37, 12.07, 12.95, 12.43, 10.94]
test_X = [2019]
 
# 数据预处理
dataset_length = len(datasets_X)
test_length = len(test_X)
# 将数据转化为numpy数组
datasets_X = np.array(datasets_X).reshape([dataset_length, 1])
test_X = np.array(test_X).reshape([test_length, 1])
datasets_Y = np.array(datasets_Y)

2.2 数据可视化

将已有的数据显示出来,并用蓝点作为标记,将每一年的横坐标都显示出来。曲线我们从二元回归曲线开始慢慢找到最符合数据趋势的曲线。

# 构造多项式特征
poly_reg = PolynomialFeatures(degree=2)
X_poly = poly_reg.fit_transform(datasets_X)
 
# 使用线性回归模型学习X_poly和datasets_Y之间的映射关系
lin_reg = LinearRegression()
lin_reg.fit(X_poly, datasets_Y)

# 数据可视化

# 蓝色显示训练数据点
plt.scatter(datasets_X, datasets_Y, color='blue')

# X轴
my_x_ticks = np.arange(1998, 2020, 1)
plt.xticks(my_x_ticks)

# 绘制线
X = np.arange(1998, 2020).reshape([-1, 1])
plt.plot(X, lin_reg.predict(poly_reg.fit_transform(X)), color='black')

plt.xlabel('Years')
plt.ylabel('Born rate')
plt.show() 

运行代码结果如下:

二元回归曲线

显然二元回归曲线并不是非常适合这些数据,有许多点分布在离直线很远的距离。让我们试试三元回归曲线,修改poly_reg变量的degree,设为3:

poly_reg = PolynomialFeatures(degree=3)

结果如下:

三元回归曲线

感觉有辣么点意思了,再试试四元回归曲线:

四元回归曲线

发现和三元回归曲线相比没有太大的变化,那我们选三元回归曲线进行预测就可以了。

2.3 数据建模

# 数据建模
# 构造三次多项式特征
poly_reg = PolynomialFeatures(degree=3)
X_poly = poly_reg.fit_transform(datasets_X)
 
# 使用线性回归模型学习X_poly和datasets_Y之间的映射关系
lin_reg_3 = LinearRegression()
lin_reg_3.fit(X_poly, datasets_Y)
 
data = poly_reg.fit_transform(test_X)
pred = lin_reg_3.predict(data)
print(pred)

预测的2019人口出生率的值为:[ 11.25692317],使用黄点表示该预测的值,得到的曲线图如下:

似乎是条挺合理的曲线,让我们拭目以待今年的人口出生率会不会是11.25,到时候记得翻出这篇文章来看看。

如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 多项式预测2019年天猫销售额

双十一刚过,天猫的销售额创新高占领了各大新闻媒体头条。但是,知乎上的一个问题对本次双十一的销售额提出了一个非常有意思的问题:《如何看待双十一销售额完美分布在三次回归曲线上且拟合高达 99.94%?是巧合还是造假?》

本文的重点放在如何用Python实现三次回归曲线的预测功能。

1.数据源

采用cnbeta新闻报道中的数据:《[直击]2019年天猫双11落幕:交易额2684亿元》

有效数字保留三位,其中2009年为0.52亿、2010年为9.36亿、2011年为52.0亿。

2.代码构建

我们将使用scikitlearn的多项式回归实现预测。训练集是2009至2014年的数据,后续测试中将陆续增加训练集至2018年。

2.1 数据预处理

构造三次多项式特征需要以列的形式,因此代码中会将numpy数组reshape成列形式。

# 数据集
datasets_X = [2009, 2010, 2011, 2012, 2013, 2014]
datasets_Y = [0.52, 9.36, 52.0, 191, 350, 571]
test_X = [2015, 2016, 2017, 2018, 2019]
real_Y =  [912, 1207, 1682, 2132, 2684]

# 数据预处理
dataset_length = len(datasets_X)
test_length = len(test_X)
# 将数据转化为numpy数组,并变为列的形式
datasets_X = np.array(datasets_X).reshape([dataset_length, 1])
test_X = np.array(test_X).reshape([test_length, 1])
datasets_Y = np.array(datasets_Y)
real_Y = np.array(real_Y)

2.2 数据建模训练

这里需要注意的是,必须先构建三次多项式特征后才可放入线性回归模型。

# 数据建模
# 构造三次多项式特征
poly_reg = PolynomialFeatures(degree=3)
X_poly = poly_reg.fit_transform(datasets_X)

# 使用线性回归模型学习X_poly和datasets_Y之间的映射关系
lin_reg_3 = LinearRegression()
lin_reg_3.fit(X_poly, datasets_Y) 

2.3 数据预测

训练完毕后,就可以将lin_reg_3模型用于预测:

data = poly_reg.fit_transform(test_X)
pred = lin_reg_3.predict(data)
print(pred) 

结果:

[ 830.64251041 1127.88919544 1457.47841358 1814.48141575 2193.96944141]

在这个训练集的基础上,预测2019年的销售额是2193亿,和真实的2684亿还是差了点。不过这样看不是很直观,让我们可视化一下数据,并逐渐增加训练集。

3.数据可视化

用 matplotlib 可以非常简单地实现这一步,设定X轴范围—绘制数据点—绘制线,最后加上横纵轴说明。

# 数据可视化
# X轴
X = np.arange(2009, 2020).reshape([-1, 1])
# 蓝色显示训练数据点
plt.scatter(datasets_X, datasets_Y, color='blue')
# 红色显示真实数据点
plt.scatter(test_X, real_Y, color='red')
# 黄色显示预测数据点
plt.scatter(test_X, pred, color='yellow')

plt.plot(X, lin_reg_3.predict(poly_reg.fit_transform(X)), color='black')
plt.xlabel('年份')
plt.ylabel('销售额(亿)')
plt.show() 

结果如下,蓝色点是训练值,红色点是真实值,而黄色的点是预测值:

训练集增加2015年的真实数据,结果如下:

有意思,真实值反而比预测值低了,说明2015年这一年的成交额非常优秀。

再增加2016年的真实数据到训练集里看一下。

现在,2017年、2018年的预测值非常接近,预测2019年的销售额是2507.3990亿元,离真实的2684亿差了100多亿。让我们继续增加2017年的真实数据到训练集中,预测2018年和2019年的销售额。

优秀,不过2019年预测的销售额为2750亿,略高于真实值2684亿,我们最后将2018年真实值加入到训练集中,看看2019年该模型的预测值是多少。

惊呆了,小红点和小黄点完美重合。按照这个模型,2020年的双十一销售额将会是3293亿元。

关注文章最下方Python实用宝典公众号二维码,回复 天猫销售额预测 或阅读原文下载查阅本模型完整源代码:

import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import r2_score

# 指定默认字体否则图片显示不了中文
from pylab import mpl
mpl.rcParams['axes.unicode_minus'] = False # 解决符号显示问题
mpl.rcParams['font.sans-serif'] = ['FangSong']

# 数据集
datasets_X = [2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018]
datasets_Y = [0.52, 9.36, 52.0, 191, 350, 571, 912, 1207, 1682, 2132]
test_X = [2019]
real_Y =  [2684]

# 数据预处理
dataset_length = len(datasets_X)
test_length = len(test_X)
# 将数据转化为numpy数组
datasets_X = np.array(datasets_X).reshape([dataset_length, 1])
test_X = np.array(test_X).reshape([test_length, 1])
datasets_Y = np.array(datasets_Y)
real_Y = np.array(real_Y)

# 数据建模
# 构造三次多项式特征
poly_reg = PolynomialFeatures(degree=3)
X_poly = poly_reg.fit_transform(datasets_X)

# 使用线性回归模型学习X_poly和datasets_Y之间的映射关系
lin_reg_3 = LinearRegression()
lin_reg_3.fit(X_poly, datasets_Y)

data = poly_reg.fit_transform(test_X)
pred = lin_reg_3.predict(data)
print(pred)

# 数据可视化
# X轴
X = np.arange(2009, 2020).reshape([-1, 1])
# 蓝色显示训练数据点
plt.scatter(datasets_X, datasets_Y, color='blue')
# 红色显示真实数据点
plt.scatter(test_X, real_Y, color='red')
# 黄色显示预测数据点
plt.scatter(test_X, pred, color='yellow')

plt.plot(X, lin_reg_3.predict(poly_reg.fit_transform(X)), color='black')
plt.xlabel('年份')
plt.ylabel('销售额(亿)')
plt.show() 

如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 你见过三行代码的爬虫吗

Python实用宝典每次讲爬虫的时候都会从“发送请求” 开始讲,讲到解析页面的时候可能大部分读者都会卡住,因为这部分确实需要一点XPATH或者CSS选择器的前置知识。那么有没有不需要这么复杂的操作就能把页面信息读取出来的方法呢?

答案是:有。

Lassie 是一个超简单的页面信息检索工具,它能够通过几行代码就获取到页面上的静态信息,比如:页面描述、视频链接、页面标题,页面关键词、图像链接等等。

为什么超简单?感受一下:

import lassie
data = lassie.fetch('https://www.zhihu.com')
print(data) 

你只要fetch一下页面,就能得到以下的运行结果(输出为字典):

(base) F:\push\20191112>python test.py
 {'images': [{'src': 'https://static.zhihu.com/static/favicon.ico', 'type': 'favicon'}], 'videos': [], 'description': '有问题,上知乎。知乎,可信赖的问答社区,以让每个人高效获得可信赖的解答为使命。知乎
 凭借认真、专业和友善的社区氛围,结构化、易获得的优质内容,基于问答的内容生产方式和独特的社区机制,吸
 引、聚集了各行各业中大量的亲历者、内行人、领域专家、领域爱好者,将高质量的内容透过人的节点来成规模地
 生产和分享。用户通过问答等交流方式建立信任和连接,打造和提升个人影响力,并发现、获得新机会。', 'locale': 'zh_CN', 'url': 'https://www.zhihu.com', 'title': '知乎 - 有问题,上知乎', 'status_code': 200} 

1.安装

如果你还没有安装Python,推荐阅读这篇文章:Python安装

安装完成后,请打开你的CMD/Terminal(终端)输入以下命令:

pip install lassie

即可成功安装lassie.

2.使用

现在,用这个工具爬取我们上篇文章的图片链接吧!

import lassie
data = lassie.fetch('https://pythondict.com/ai/python-suicide-detect-svm/')
print(data['images'])

结果:

[{'src': 'https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2019/11/2019111013222864.png', 'secure_src': 'https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2019/11/2019111013222864.png', 'type': 'og:image'}, {'src': 
 'https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2019/11/2019111013222864.png', 'type': 'twitter:image'}, 
 {'src': 'https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2019/07/2019073115192114.jpg', 'type': 'favicon'}]

当然,我们还可以用列表解析式,把所有链接放到一个数组里:

print([i['src'] for i in data['images']])

结果:

['https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2019/11/2019111013222864.png', 'https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2019/11/2019111013222864.png', 'https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2019/07/2019073115192114.jpg']

怎么样,是不是这个工具拿来爬静态页面实在太方便了!唯一的缺点就是它无法爬取页面中详细的文本内容,仅仅只能用来提取图片、视频和页面相关的信息,如果你的爬虫是只需要爬取静态页面上的图片和视频,那这个简直是神器啊。

如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 短文本自动识别个体是否有自杀倾向

上一篇文章,我们以微博树洞为例,讲解了怎么自动爬取单个微博的评论。今天我们就要用上这些数据做一个自杀倾向分类器,这样的分类器如果应用得当,将可以帮助成千上万误入歧途的人们挽回生命。

为了简化问题,我们将短文本分为两种类别中的一种,即要么是正常微博、要么是自杀倾向微博。这样,有了上次的微博树洞,训练集和测试集就非常好获得了。由于是短文本二分类问题,可以使用scikit-learn的SVM分类模型。

不过要注意的是,我们的分类器并不能保证分类出来的结果百分百正确,毕竟心理状态是很难通过文本准确识别出来的,我们只能通过文字,大致判断其抑郁情况并加以介入。实际上这是一个宁可错杀一百,不可放过一个的问题。毕竟放过一个,可能就有一条生命悄然流逝。

本文源代码: https://github.com/Ckend/suicide-detect-svm 欢迎一同改进这个项目,在训练集和模型方面,改进的空间还相当大。如果你访问不了github,请关注文章最下方公众号,回复自杀倾向检测获得本项目完整源代码。

2023-04-26更新:

提供一个5W行的数据源,数据结构请自行组合:https://pythondict.com/download/%e8%b5%b0%e9%a5%ad%e5%be%ae%e5%8d%9a%e8%af%84%e8%ae%ba%e6%95%b0%e6%8d%ae/

1.数据准备

数据集整体上分两个部分,一部分是训练集、一部分是测试集。其中,训练集和测试集中还要分为正常微博短文本和自杀倾向短文本。

将上一篇爬取微博树洞的文章中得到的数据进行人工筛选后,挑出300条作为训练集(有点少,其实业界至少也要3000条以上),再根据上次的微博爬虫随意爬取10000条微博作为训练集的正常微博类。另外再分别搜集自杀倾向微博和普通微博各50条作为测试集。

每条微博按行存储在txt文件里。训练集中,正常微博命名为normal.txt, 自杀倾向微博命名为die.txt。测试集存放在后缀为_test.txt的文件中:

此外,接下来我们会使用到一个机器学习工具包叫scikit-learn(sklearn),其打包好了许多机器学习模型和预处理的方法,方便我们构建分类器,在CMD/Terminal输入以下命令安装:

pip install -U scikit-learn

如果你还没有安装Python,请看这篇文章安装Python,然后再执行上述命令安装sklearn.

2.数据预处理

我们使用一个典型的中文自然语言预处理方法:对文本使用结巴分词后将其数字化。

由于具有自杀倾向的微博中,其实类似于”死”、”不想活”、”我走了”等这样的词语比较常见,因此我们可以用TF-IDF将字符串数字化。如果你不了解TF-IDF,请看这篇文章: 文本处理之 tf-idf 算法及其实践

数字化的部分代码如下。

print('(2) doc to var...')
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer

# CountVectorizer考虑每种词汇在该训练文本中出现的频率,得到计数矩阵
count_v0= CountVectorizer(analyzer='word',token_pattern='\w{1,}')
counts_all = count_v0.fit_transform(all_text)

count_v1= CountVectorizer(vocabulary=count_v0.vocabulary_)
counts_train = count_v1.fit_transform(train_texts) 
print("the shape of train is "+repr(counts_train.shape)  )
count_v2 = CountVectorizer(vocabulary=count_v0.vocabulary_)
counts_test = count_v2.fit_transform(test_texts)
print("the shape of test is "+repr(counts_test.shape)  )

# 保存数字化后的词典
joblib.dump(count_v0.vocabulary_, "model/die_svm_20191110_vocab.m")

counts_all = count_v2.fit_transform(all_text)
print("the shape of all is "+repr(counts_all.shape))

# 将计数矩阵转换为规格化的tf-idf格式
tfidftransformer = TfidfTransformer()  
train_data = tfidftransformer.fit(counts_train).transform(counts_train)
test_data = tfidftransformer.fit(counts_test).transform(counts_test)
all_data = tfidftransformer.fit(counts_all).transform(counts_all) 

3.训练

使用scikit-learn的SVM分类模型,我们能很快滴训练并构建出一个分类器:

print('(3) SVM...')
from sklearn.svm import SVC

# 使用线性核函数的SVM分类器,并启用概率估计(分别显示分到两个类别的概率如:[0.12983359 0.87016641])
svclf = SVC(kernel = 'linear', probability=True) 

# 开始训练
svclf.fit(x_train,y_train)
# 保存模型
joblib.dump(svclf, "model/die_svm_20191110.m")

这里我们忽略了SVM原理的讲述,SVM的原理可以参考这篇文章:支持向量机(SVM)——原理篇

4.测试

测试的时候,我们要分别计算模型对两个类别的分类精确率和召回率。scikit-learn提供了一个非常好用的函数classification_report来计算它们:

# 测试集进行测试
preds = svclf.predict(x_test)
y_preds = svclf.predict_proba(x_test)

preds = preds.tolist()
for i,pred in enumerate(preds):
    # 显示被分错的微博
    if int(pred) != int(y_test[i]):
        try:
            print(origin_eval_text[i], ':', test_texts[i], pred, y_test[i], y_preds[i])
        except Exception as e:
            print(e)

# 分别查看两个类别的准确率、召回率和F1值
print(classification_report(y_test, preds)) 

结果:

对自杀倾向微博的分类精确率为100%,但是查全率不够,它只找到了50条里的60%,也就是30条自杀倾向微博。

对于正常微博的分类,其精确率为71%,也就是说有部分正常微博被分类为自杀倾向微博,不过其查全率为100%,也就是不存在不被分类的正常微博。

这是建立在训练集还不够多的情况下的结果。我们的自杀倾向微博的数据仅仅才300条,这是远远不够的,如果能增加到3000条,相信结果会改进不少,尤其是对于自杀倾向微博的查全率有很大的帮助。预估最终该模型的精确率和召回率至少能达到95%。

本文源代码: https://github.com/Ckend/suicide-detect-svm 欢迎一同改进这个项目。如果你访问不了github,请关注文章最下方公众号,回复自杀倾向检测获得本项目完整源代码。

如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 爬取“微博树洞”详细教程

最近要做一个关于自动从微博等短文本数据中判断人是否有自杀倾向的项目,在这之前需要先收集许多具有自杀倾向的人发的微博或短文本数据作为训练集。

其实这样的数据是挺难找的,尤其是对于我这种需求量比较大的项目。不过好在最后发现了突破口:“微博树洞”。“微博树洞”是指宣告了自杀行为的过世的人的微博,其留言区成为成千上万的抑郁症或是绝望的人的归属,在其下方发布许多负能量甚至是寻死的宣言。

比如走饭的微博:

1.找到微博评论数据接口

微博评论的数据接口有两种,一种是手机版、一种是PC版。手机版能爬到的数据仅仅只有十五页,因此我们从PC版入手,先来看看PC版的接口怎么找,长啥样儿。

首先,在当前微博的页面右键—检查(F12)打开开发者工具,然后按照下图的步骤进行操作(选择NetWork—选择XHR—随便点击另一个评论页—查看右侧新增的请求):

然后我们看新增的请求,你会发现在Preview中能看到格式化后的数据,而且里面有个html,仔细观察这个html你会发现这个就是评论列表的数据。我们仅需要将这个html解析出来即可。

再看看get请求的URL:

https://weibo.com/aj/v6/comment/big?ajwvr=6&id=3424883176420210&page=2&__rnd=1573219876141

ajwvr是一个固定值为6、id是指想要爬取评论的微博id、page是指第几页评论、_rnd是请求时的毫秒级时间戳。

不过微博是要求登录才能看更多评论的,因此我们需要先访问微博,拿到cookie的值才能开始爬。

2.编写爬虫

关注文章最下方的Python实用宝典,回复微博评论爬虫即可获得本项目的完整源代码。

设定四个参数:

    params = {
        'ajwvr': 6,
        'id': '3424883176420210',
        'page': 1,
        '_rnd': int(round(time.time() * 1000))
    } 

设定cookie:

headers = { 
    'X-Requested-With': 'XMLHttpRequest', 
    'Cookie': '你的微博cookie',
} 

发送请求并解析数据

    URL = 'https://weibo.com/aj/v6/comment/big'

    for num in range(1,51,1):
        print(f'============== 正在爬取第 {num} 页 ====================')
        params['page'] = num
        params['_rnd'] = int(round(time.time() * 1000))
        resp = requests.get(URL, params=params, headers=headers)
        resp = json.loads(resp.text) 

解析这串HTML中我们所需要的数据,这里用到了XPATH,如果你还不了解XPATH,可以看这篇文章: 学爬虫利器XPath,看这一篇就够了

         if resp['code'] == '100000':
            html = resp['data']['html']
            html = etree.HTML(html)
            data = html.xpath('//div[@node-type="comment_list"]')
            for i in data:
                # 评论人昵称
                nick_name = i.xpath('.//div[@class="WB_text"]/a[1]/text()')
                # 评论内容
                text = i.xpath('.//div[@class="WB_text"]')
                text = [i.xpath('string(.)') for i in text]
                # 头像地址
                pic_url = i.xpath('.//div[@class="WB_face W_fl"]/a/img/@src')
                print(len(nick_name),len(text),len(pic_url))
                write_comment([i.strip() for i in text], pic_url, nick_name) 

其中写入文件的函数和下载图片的函数如下:

# 下载图片
def download_pic(url, nick_name):
    if not url:
        return
    if not os.path.exists(pic_file_path):
        os.mkdir(pic_file_path)
    resp = requests.get(url)
    if resp.status_code == 200:
        with open(pic_file_path + f'/{nick_name}.jpg', 'wb') as f:
            f.write(resp.content)

# 写入留言内容
def write_comment(comment, pic_url, nick_name):
    f = open('comment.txt', 'a', encoding='utf-8')
    for index, i in enumerate(comment):
        if ':' not in i and '回复' not in i and i != '':
            # 去除评论的评论
            w_comment = i.strip().replace(':', '').replace('\n', '')
            # 写入评论
            f.write(w_comment.replace('等人', '').replace('图片评论', '')+'\n')
            # 获得头像
            download_pic(pic_url[index], nick_name[index]) 

以上就是我们所用到的代码。在公众号后台回复 微博评论爬虫 即可下载完整源代码(附手机版爬虫)。

3.定时爬虫

尽管如此,我们得到的数据还是不够,PC版的微博评论页面也仅仅支持爬到第五十页,第五十一页后就拿不到数据了,如图:

不过,走饭这个微博真的很多人回复,一天的数据就差不多50页了,我们可以通过每天定时爬50页来获取数据。linux系统可以使用crontab定时脚本实现,windows系统可以通过计划任务实现,这里讲讲crontab实现方法。

假设你的Python存放在/usr/bin/且将脚本命名为weibo.py 存放在home中,在终端输入crontab -e后,在最后面增加上这一条语句即可:

0 0 * * * /usr/bin/python /home/weibo.py

在公众号后台回复 微博评论爬虫 即可下载本文完整源代码(附手机版爬虫) 。

如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

有趣好用的Python教程

退出移动版
微信支付
请使用 微信 扫码支付