分类目录归档:Python 数据分析

Altair 一个漂亮易用的统计可视化库,甚至可拖动计数!

Altair 是一个基于Jupyter Notebook的强大可视化库。它提供了强大而简洁的可视化语法,使我们能够快速构建各种统计可视化图表。

通过下面10行代码,你就能创建一个可交互的散点图:

import altair as alt

from vega_datasets import data
cars = data.cars()

alt.Chart(cars).mark_point().encode(
    x='Horsepower',
    y='Miles_per_Gallon',
    color='Origin',
).interactive()

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install altair vega_datasets

2.Altair 基本使用

Altair 中的数据是围绕 Pandas Dataframe 构建的。

我们首先导入 Pandas 并创建一个简单的 DataFrame 以进行可视化,a 列中有一个分类变量,b 列有一个数值变量:

import pandas as pd
data = pd.DataFrame({'a': list('CCCDDDEEE'),
                     'b': [2, 7, 4, 1, 2, 6, 8, 4, 7]})

Altair 中的基本对象是Chart,它将上述的数据作为单个参数:

import altair as alt
chart = alt.Chart(data)

到目前为止,我们已经定义了 Chart 对象,但是我们还没有告诉图表对数据任何事情。接下来会出现。

有了这个图表对象,我们现在可以指定我们希望如何可视化数据,比如作为点:

alt.Chart(data).mark_point()

然后对数据进行编码,比如指定 a 列为x,b列为y:

alt.Chart(data).mark_point().encode(
    x='a', y='b'
)

效果如下:

如果你希望聚合求得某列得平均值,你还可以这么做:

alt.Chart(data).mark_point().encode(
    x='a',
    y='average(b)'
)

如果你希望使用柱状图,只需要把mark_point改为mark_bar:

alt.Chart(data).mark_bar().encode(
    x='a',
    y='average(b)'
)

还可以获得水平柱状图,我们只需要把x和y对调一下:

alt.Chart(data).mark_bar().encode(
    y='a',
    x='average(b)'
)

除了点状图和柱状图,Altair 还支持几十种图表类型:

更多的图表类型请在官网查看:

https://altair-viz.github.io/gallery/index.html

3.高级使用

你可以给图表自定义你喜欢的颜色和对应的横坐标纵坐标标题:

alt.Chart(data).mark_bar(color='firebrick').encode(
    alt.Y('a', title='category'),
    alt.X('average(b)', title='avg(b) by category')
)

你还可以将图表保存为HTML:

chart = alt.Chart(data).mark_bar().encode(
    x='a',
    y='average(b)',
)
chart.save('chart.html')

如果你希望能够通过区间选择数据点并计数,你可以这么做:

import altair as alt
from vega_datasets import data

source = data.cars()

brush = alt.selection(type='interval')

points = alt.Chart(source).mark_point().encode(
    x='Horsepower',
    y='Miles_per_Gallon',
    color=alt.condition(brush, 'Origin', alt.value('lightgray'))
).add_selection(
    brush
)

bars = alt.Chart(source).mark_bar().encode(
    y='Origin',
    color='Origin',
    x='count(Origin)'
).transform_filter(
    brush
)

points & bars

跟牛逼的是,Altair还可以做多图表联动:

# 公众号:Python实用宝典 整合
import altair as alt
from vega_datasets import data

cars = data.cars.url
brush = alt.selection_interval()

chart = alt.Chart(cars).mark_point().encode(
    y='Horsepower:Q',
    color=alt.condition(brush, 'Origin:N', alt.value('lightgray'))
).properties(
    width=250,
    height=250
).add_selection(
    brush
)

chart.encode(x='Acceleration:Q') | chart.encode(x='Miles_per_Gallon:Q')

左边圈起来的 Acceleration 数据点,右边会对应显示其 Miles_per_Gallon 数据点:

除了这些,Altair还有更多的交互功能,比如选择框拖动、比例绑定、自动响应、表达式选择等等,你可以阅读 Altair 官网学习并使用:

https://altair-viz.github.io/user_guide/interactions.html

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

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

AutoGrad 这个Python神器能够帮你自动计算函数斜率和梯度

AutoGrad 是一个老少皆宜的 Python 梯度计算模块。

对于初高中生而言,它可以用来轻易计算一条曲线在任意一个点上的斜率。

对于大学生、机器学习爱好者而言,你只需要传递给它Numpy这样的标准数据库下编写的损失函数,它就可以自动计算损失函数的导数(梯度)。

我们将从普通斜率计算开始,介绍到如何只使用它来实现一个逻辑回归模型。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install autograd

2.AutoGrad 计算斜率

对于初高中生同学而言,它可以用来轻松计算斜率,比如我编写一个斜率为0.5的直线函数:

# 公众号 Python实用宝典
import autograd.numpy as np
from autograd import grad


def oneline(x):
    y = x/2
    return y

grad_oneline = grad(oneline)
print(grad_oneline(3.0))

运行代码,传入任意X值,你就能得到在该X值下的斜率:

(base) G:\push\20220724>python 1.py
0.5

由于这是一条直线,因此无论你传什么值,都只会得到0.5的结果。

那么让我们再试试一个tanh函数:

# 公众号 Python实用宝典
import autograd.numpy as np
from autograd import grad

def tanh(x):
    y = np.exp(-2.0 * x)
    return (1.0 - y) / (1.0 + y)
grad_tanh = grad(tanh)
print(grad_tanh(1.0))

此时你会获得 1.0 这个 x 在tanh上的曲线的斜率:

(base) G:\push\20220724>python 1.py
0.419974341614026

我们还可以绘制出tanh的斜率的变化的曲线:

# 公众号 Python实用宝典
import autograd.numpy as np
from autograd import grad


def tanh(x):
    y = np.exp(-2.0 * x)
    return (1.0 - y) / (1.0 + y)
grad_tanh = grad(tanh)
print(grad_tanh(1.0))

import matplotlib.pyplot as plt
from autograd import elementwise_grad as egrad
x = np.linspace(-7, 7, 200)
plt.plot(x, tanh(x), x, egrad(tanh)(x))
plt.show()

图中蓝色的线是tanh,橙色的线是tanh的斜率,你可以非常清晰明了地看到tanh的斜率的变化。非常便于学习和理解斜率概念。

3.实现一个逻辑回归模型

有了Autograd,我们甚至不需要借用scikit-learn就能实现一个回归模型:

逻辑回归的底层分类就是基于一个sigmoid函数:

import autograd.numpy as np
from autograd import grad

# Build a toy dataset.
inputs = np.array([[0.52, 1.12,  0.77],
                   [0.88, -1.08, 0.15],
                   [0.52, 0.06, -1.30],
                   [0.74, -2.49, 1.39]])
targets = np.array([True, True, False, True])

def sigmoid(x):
    return 0.5 * (np.tanh(x / 2.) + 1)

def logistic_predictions(weights, inputs):
    # Outputs probability of a label being true according to logistic model.
    return sigmoid(np.dot(inputs, weights))

从下面的损失函数可以看到,预测结果的好坏取决于weights的好坏,因此我们的问题转化为怎么优化这个 weights 变量:

def training_loss(weights):
    # Training loss is the negative log-likelihood of the training labels.
    preds = logistic_predictions(weights, inputs)
    label_probabilities = preds * targets + (1 - preds) * (1 - targets)
    return -np.sum(np.log(label_probabilities))

知道了优化目标后,又有Autograd这个工具,我们的问题便迎刃而解了,我们只需要让weights往损失函数不断下降的方向移动即可:

# Define a function that returns gradients of training loss using Autograd.
training_gradient_fun = grad(training_loss)

# Optimize weights using gradient descent.
weights = np.array([0.0, 0.0, 0.0])
print("Initial loss:", training_loss(weights))
for i in range(100):
    weights -= training_gradient_fun(weights) * 0.01

print("Trained loss:", training_loss(weights))

运行结果如下:

(base) G:\push\20220724>python regress.py
Initial loss: 2.772588722239781
Trained loss: 1.067270675787016

由此可见损失函数以及下降方式的重要性,损失函数不正确,你可能无法优化模型。损失下降幅度太单一或者太快,你可能会错过损失的最低点。

总而言之,AutoGrad是一个你用来优化模型的一个好工具,它可以给你提供更加直观的损失走势,进而让你有更多优化想象力。有兴趣的朋友还可以看官方的更多示例代码:

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

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

Pandas TA 一个能帮助你迅速计算量化投资技术指标的神器

Pandas TA 是一个基于Pandas模块开发的,具有上百个技术指标和常用指标的开源模块。它包括但不限于能够绘制62种蜡烛形态(晨星、乌云、十字星、孕线等等)、130个技术指标,如移动平均线、macd、hma、布林带、obv、aron、squeeze等等各种指标。

下面就来讲一下这个量化投资神器的安装和使用方法,如果对你有帮助,记得点个赞和在看支持一下哦。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install pandas_ta

此外,如果你想使用上全部指标,你需要安装TA-Lib

pip install Ta-Lib

安装TA-Lib的时候可能会遇到没有VC++14.0的报错,这时候我们需要手动安装,在 https://www.lfd.uci.edu/~gohlke/pythonlibs/#ta-lib 中下载你对应的Python版本的 TA-Lib whl文件。

下载完成后执行以下命令:

# 公众号:二七阿尔量化
pip install D:\path\TA_lib‑0.4.24‑cp38‑cp38‑win_amd64.whl

就能成功手动安装 Ta-lib

2.Pandas TA 基本使用

为了方便介绍使用方法,我下载了沪深300的分钟级数据,如果你需要本文的全部代码及数据,请在二七阿尔量化公众号后台回复:pandas_ta 下载。

首先看看我们的数据类型:

# 公众号:二七阿尔量化
import pandas as pd
import pandas_ta as ta

sh300data = pd.read_csv("sh300_1min.csv")

print(sh300data)

#        Unnamed: 0                  day      open      high       low     close     volume
# 0               0  2022-03-07 10:47:00  4406.223  4406.352  4405.662  4405.922   54345400
# 1               1  2022-03-07 10:48:00  4406.172  4406.175  4403.834  4403.918   70803100
# 2               2  2022-03-07 10:49:00  4403.333  4403.333  4402.235  4402.340   49632500
# 3               3  2022-03-07 10:50:00  4402.330  4402.519  4401.838  4402.519   48159200

默认情况下,pandas ta 取  open 、high、low、close、volumeadj_close 列作为指标参数,本文的列名正好对应的上,无需再去特别命名。

先试试收益率计算:

sh300data = sh300data.set_index("day")
print(sh300data.ta.log_return(cumulative=True, append=True))
# 2022-03-07 10:47:00    0.000000
# 2022-03-07 10:48:00   -0.000455
# 2022-03-07 10:49:00   -0.000813
# 2022-03-07 10:50:00   -0.000773
# 2022-03-07 10:51:00   -0.000826

验证一下结果:

>>> (- 4405.922 + 4403.918) / 4405.922
-0.00045484236897518966
>>> (- 4403.918 + 4402.34) / 4403.918
-0.00035831729836920665
>>> -0.00045484236897518966 + -0.00035831729836920665
-0.0008131596673443963

结果对得上,注意我们传递了cumulative=True参数,因此每次都会将前面的收益率累加。

试一下常用指标 sma:

sma10 = sh300data.ta.sma(length=10)
print(sma10)
# day
# 2022-03-07 10:47:00          NaN
# 2022-03-07 10:48:00          NaN
# 2022-03-07 10:49:00          NaN
# 2022-03-07 10:50:00          NaN
# 2022-03-07 10:51:00          NaN
#                          ...
# 2022-07-08 14:55:00    4429.3936
# 2022-07-08 14:56:00    4428.9421
# 2022-07-08 14:57:00    4428.5996
# 2022-07-08 14:58:00    4428.3280
# 2022-07-08 15:00:00    4428.1877
# Name: SMA_10, Length: 20000, dtype: float64

支持以下全部技术指标:aberration, above, above_value, accbands, ad, adosc, adx, alma, amat, ao, aobv, apo, aroon, atr, bbands, below, below_value, bias, bop, brar, cci, cdl_pattern, cdl_z, cfo, cg, chop, cksp, cmf, cmo, coppock, cross, cross_value, cti, decay, decreasing, dema, dm, donchian, dpo, ebsw, efi, ema, entropy, eom, er, eri, fisher, fwma, ha, hilo, hl2, hlc3, hma, hwc, hwma, ichimoku, increasing, inertia, jma, kama, kc, kdj, kst, kurtosis, kvo, linreg, log_return, long_run, macd, mad, massi, mcgd, median, mfi, midpoint, midprice, mom, natr, nvi, obv, ohlc4, pdist, percent_return, pgo, ppo, psar, psl, pvi, pvo, pvol, pvr, pvt, pwma, qqe, qstick, quantile, rma, roc, rsi, rsx, rvgi, rvi, short_run, sinwma, skew, slope, sma, smi, squeeze, squeeze_pro, ssf, stc, stdev, stoch, stochrsi, supertrend, swma, t3, td_seq, tema, thermo, tos_stdevall, trima, trix, true_range, tsi, tsignals, ttm_trend, ui, uo, variance, vhf, vidya, vortex, vp, vwap, vwma, wcp, willr, wma, xsignals, zscore

试一下十字星(Doji Candlestick)形态:

doji = sh300data.ta.cdl_pattern(name="doji")
print(doji)
#                      CDL_DOJI_10_0.1
# day
# 2022-03-07 10:47:00              0.0
# 2022-03-07 10:48:00              0.0
# 2022-03-07 10:49:00              0.0
# 2022-03-07 10:50:00              0.0
# 2022-03-07 10:51:00              0.0
# ...                              ...
# 2022-07-08 14:55:00              0.0
# 2022-07-08 14:56:00            100.0
# 2022-07-08 14:57:00              0.0
# 2022-07-08 14:58:00              0.0
# 2022-07-08 15:00:00              0.0

这里的值如果出现 100 ,就是出现DOJI形态。支持以下全部蜡烛形态:

2crows, 3blackcrows, 3inside, 3linestrike, 3outside, 3starsinsouth, 3whitesoldiers, abandonedbaby, advanceblock, belthold, breakaway, closingmarubozu, concealbabyswall, counterattack, darkcloudcover, doji, dojistar, dragonflydoji, engulfing, eveningdojistar, eveningstar, gapsidesidewhite, gravestonedoji, hammer, hangingman, harami, haramicross, highwave, hikkake, hikkakemod, homingpigeon, identical3crows, inneck, inside, invertedhammer, kicking, kickingbylength, ladderbottom, longleggeddoji, longline, marubozu, matchinglow, mathold, morningdojistar, morningstar, onneck, piercing, rickshawman, risefall3methods, separatinglines, shootingstar, shortline, spinningtop, stalledpattern, sticksandwich, takuri, tasukigap, thrusting, tristar, unique3river, upsidegap2crows, xsidegap3methods

由于62种蜡烛形态太多了,你可能需要一次性捞出来,Pandas TA也支持你这么做:

# 公众号:二七阿尔量化
import pandas as pd
import pandas_ta as ta

sh300data = pd.read_csv("sh300_1min.csv")
sh300data = sh300data.set_index("day")
all_candle = sh300data.ta.cdl_pattern(name="all")
print(all_candle)
#                      CDL_2CROWS  CDL_3BLACKCROWS  CDL_3INSIDE  ...  CDL_UNIQUE3RIVER  CDL_UPSIDEGAP2CROWS  CDL_XSIDEGAP3METHODS
# day                                                            ...
# 2022-03-07 10:47:00         0.0              0.0          0.0  ...               0.0                  0.0                   0.0      
# 2022-03-07 10:48:00         0.0              0.0          0.0  ...               0.0                  0.0                   0.0      
# 2022-03-07 10:49:00         0.0              0.0          0.0  ...               0.0                  0.0                   0.0      
# 2022-03-07 10:50:00         0.0              0.0          0.0  ...               0.0                  0.0                   0.0      
# 2022-03-07 10:51:00         0.0              0.0          0.0  ...               0.0                  0.0                   0.0      
# ...                         ...              ...          ...  ...               ...                  ...                   ...      
# 2022-07-08 14:55:00         0.0              0.0          0.0  ...               0.0                  0.0                   0.0      
# 2022-07-08 14:56:00         0.0              0.0          0.0  ...               0.0                  0.0                   0.0      
# 2022-07-08 14:57:00         0.0              0.0        100.0  ...               0.0                  0.0                   0.0      
# 2022-07-08 14:58:00         0.0              0.0          0.0  ...               0.0                  0.0                   0.0      
# 2022-07-08 15:00:00         0.0              0.0          0.0  ...               0.0                  0.0                   0.0      

# [20000 rows x 62 columns]

3.高级使用

Pandas TA 还支持策略的使用:

# 公众号:二七阿尔量化
import pandas as pd
import pandas_ta as ta
from multiprocessing import Process, freeze_support

sh300data = pd.read_csv("sh300_1min.csv")
sh300data = sh300data.set_index("day")
CustomStrategy = ta.Strategy(
    name="Momo and Volatility",
    description="SMA 50,200, BBANDS, RSI, MACD and Volume SMA 20",
    ta=[
        {"kind": "sma", "length": 50},
        {"kind": "sma", "length": 200},
        {"kind": "bbands", "length": 20},
        {"kind": "rsi"},
        {"kind": "macd", "fast": 8, "slow": 21},
        {"kind": "sma", "close": "volume", "length": 20, "prefix": "VOLUME"},
    ]
)


if __name__ == '__main__':
    freeze_support()
    sh300data.ta.strategy(CustomStrategy)
    print(sh300data)
    #                          Unnamed: 0      open      high       low  ...  MACD_8_21_9  MACDh_8_21_9  MACDs_8_21_9  VOLUME_SMA_20
    # day                                                            ...
    # 2022-03-07 10:47:00           0  4406.223  4406.352  4405.662  ...          NaN           NaN           NaN            NaN        
    # 2022-03-07 10:48:00           1  4406.172  4406.175  4403.834  ...          NaN           NaN           NaN            NaN        
    # 2022-03-07 10:49:00           2  4403.333  4403.333  4402.235  ...          NaN           NaN           NaN            NaN        
    # 2022-03-07 10:50:00           3  4402.330  4402.519  4401.838  ...          NaN           NaN           NaN            NaN        
    # 2022-03-07 10:51:00           4  4402.376  4402.699  4402.129  ...          NaN           NaN           NaN            NaN        
    # ...                         ...       ...       ...       ...  ...          ...           ...           ...            ...        
    # 2022-07-08 14:55:00       19995  4428.123  4428.371  4427.098  ...    -1.700179     -0.244194     -1.455985     50578250.0        
    # 2022-07-08 14:56:00       19996  4427.209  4427.688  4426.886  ...    -1.725356     -0.215496     -1.509860     53128625.0        
    # 2022-07-08 14:57:00       19997  4427.279  4428.605  4427.279  ...    -1.583555     -0.058956     -1.524599     55393515.0        
    # 2022-07-08 14:58:00       19998  4428.268  4428.458  4428.268  ...    -1.426088      0.078808     -1.504897     53840375.0        
    # 2022-07-08 15:00:00       19999  4427.963  4428.781  4427.963  ...    -1.241029      0.211094     -1.452123     60235755.0        

    # [20000 rows x 18 columns]

可以看到,策略其实就是让你将一些技术指标提前配置好,通过调用策略能够自动将这些技术指标附加到你的数据集上,非常方便。

此外,策略计算的时候会用到多进程,多进程的并行数量也是可以控制的:

# 设置为4个核心,即最多4个并行
sh300data.ta.cores = 4

# 设置为0则不用多进程
sh300data.ta.cores = 0

# 查看并行数量
print(sh300data.ta.cores)
# 0

好啦,关于Pandas TA我们就先介绍到这里啦,如果你需要了解更多内容,可以访问官方文档:

https://github.com/twopirllc/pandas-ta

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

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

Cpca 这个Python神器能帮你自动识别文字中的省市区并绘图

在做NLP(自然语言处理)相关任务时,经常会遇到需要识别并提取省、城市、行政区的需求。虽然我们自己通过关键词表一个个查找也能实现提取目的,但是需要先搜集省市区关键词表,相对而言比较繁琐。

今天给大家介绍一个模块,你只需要把字符串传递给这个模块,他就能给你返回这个字符串内的省、市、区关键词,并能给你在图片上标注起来,它就是 Cpca 模块。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install cpca

注意,目前 cpca 模块仅支持Python3及以上版本。

在 windows 上可能会出现类似如下问题

Building wheel for pyahocorasick (setup.py) ... error

先去下载 Microsoft Visual C++ Build Tools 安装VC++构建工具,再重新 pip install cpca,即可解决问题

2.Cpca 基本使用

通过两行代码就能实现最基本的省市区提取:

# 公众号: Python 实用宝典
# 2022/06/23

import cpca

location_str = [
    "广东省深圳市福田区巴丁街深南中路1025号新城大厦1层",
    "特斯拉上海超级工厂是特斯拉汽车首座美国本土以外的超级工厂,位于中华人民共和国上海市。",
    "三星堆遗址位于中国四川省广汉市城西三星堆镇的鸭子河畔,属青铜时代文化遗址"
]
df = cpca.transform(location_str)
print(df)

效果如下:

     省     市     区                     地址  adcode
0  广东省   深圳市   福田区     巴丁街深南中路1025号新城大厦1层  440304
1  上海市  None  None                      。  310000
2  四川省   德阳市   广汉市  城西三星堆镇的鸭子河畔,属青铜时代文化遗址  510681

注意第三条的广汉市,cpca 不仅识别到了语句中的县级市广汉市,还能自动匹配到其代管市的德阳市,不得不说非常强大。

如果你想获知程序是从字符串的那个位置提取出省市区名的,可以添加一个 pos_sensitive=True 参数:

# 公众号: Python 实用宝典
# 2022/06/23

import cpca

location_str = [
    "广东省深圳市福田区巴丁街深南中路1025号新城大厦1层",
    "特斯拉上海超级工厂是特斯拉汽车首座美国本土以外的超级工厂,位于中华人民共和国上海市。",
    "三星堆遗址位于中国四川省广汉市城西三星堆镇的鸭子河畔,属青铜时代文化遗址"
]
df = cpca.transform(location_str, pos_sensitive=True)
print(df)

效果如下:

(base) G:\push\20220623>python 1.py
     省     市     区                     地址  adcode  省_pos  市_pos  区_pos
0  广东省   深圳市   福田区     巴丁街深南中路1025号新城大厦1层  440304      0      3      6
1  上海市  None  None                      。  310000     38     -1     -1
2  四川省   德阳市   广汉市  城西三星堆镇的鸭子河畔,属青铜时代文化遗址  510681      9     -1     12

它标记出了识别到省、市、区的关键位置(index),当然如果是德阳市这种特殊的识别会被标记为-1.

3.高级使用

它还可以从大段文本中批量识别多个地区:

# 公众号: Python 实用宝典
# 2022/06/23

import cpca

long_text = "对一个城市的评价总会包含个人的感情。如果你喜欢一个城市,很有可能是喜欢彼时彼地的自己。"\
    "在广州、香港读过书,工作过,在深圳买过房、短暂生活过,去北京出了几次差。"\
    "想重点比较一下广州、深圳和香港,顺带说一下北京。总的来说,觉得广州舒适、"\
    "香港精致、深圳年轻气氛好、北京大气又粗糙。答主目前选择了广州。"
df = cpca.transform_text_with_addrs(long_text, pos_sensitive=True)
print(df)

效果如下:

(base) G:\push\20220623>python 1.py
          省     市     区 地址  adcode  省_pos  市_pos  区_pos
0       广东省   广州市  None     440100     -1     44     -1
1   香港特别行政区  None  None     810000     47     -1     -1
2       广东省   深圳市  None     440300     -1     58     -1
3       北京市  None  None     110000     71     -1     -1
4       广东省   广州市  None     440100     -1     86     -1
5       广东省   深圳市  None     440300     -1     89     -1
6   香港特别行政区  None  None     810000     92     -1     -1
7       北京市  None  None     110000    100     -1     -1
8       广东省   广州市  None     440100     -1    110     -1
9   香港特别行政区  None  None     810000    115     -1     -1
10      广东省   深圳市  None     440300     -1    120     -1
11      北京市  None  None     110000    128     -1     -1
12      广东省   广州市  None     440100     -1    143     -1

不仅如此,模块中还自带一些简单绘图工具,可以在地图上将上面输出的数据以热力图的形式画出来:

# 公众号: Python 实用宝典
# 2022/06/23

import cpca
from cpca import drawer

long_text = "对一个城市的评价总会包含个人的感情。如果你喜欢一个城市,很有可能是喜欢彼时彼地的自己。"\
    "在广州、香港读过书,工作过,在深圳买过房、短暂生活过,去北京出了几次差。"\
    "想重点比较一下广州、深圳和香港,顺带说一下北京。总的来说,觉得广州舒适、"\
    "香港精致、深圳年轻气氛好、北京大气又粗糙。答主目前选择了广州。"
df = cpca.transform_text_with_addrs(long_text, pos_sensitive=True)
drawer.draw_locations(df[cpca._ADCODE], "df.html")

运行的时候可能会报这个错:

(base) G:\push\20220623>python 1.py
Traceback (most recent call last):
  File "1.py", line 12, in <module>
    drawer.draw_locations(df[cpca._ADCODE], "df.html")
  File "G:\Anaconda3\lib\site-packages\cpca\drawer.py", line 41, in draw_locations
    import folium
ModuleNotFoundError: No module named 'folium'

使用pip安装即可:

pip install folium

然后重新运行代码,会在当前目录下生成 df.html, 双击打开,效果如下:

怎么用,是不是感觉非常方便?以后地点的识别用这个模块就完全够了。

还有更多的细节你可以访问这个项目的Github主页阅读,该项目的README完全中文编写,非常容易阅读:

https://github.com/DQinYuan/chinese_province_city_area_mapper

如果你无法访问GitHub,也可以在Python实用宝典公众号后台回复:cpca 下载完整项目。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

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

超实用!yfinance 教你 Python 获取并下载美股数据

yfinance 是一个使用 Yahoo! 获取数据的 Python 第三方模块。它支持获取最细到1分钟级的历史数据及股票基本面数据,是免费获得美股分钟级及以上粒度数据的不二之选。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install yfinance

2.yfinance 基本使用

通过yfinance你可以使用一样命令下载任意美股股票的数据,比如:

import yfinance as yf

# 单股
data = yf.download("AAPL", start="2017-01-01", end="2017-04-30")
#                  Open       High        Low      Close  Adj Close     Volume
# Date
# 2017-01-03  28.950001  29.082500  28.690001  29.037500  27.257641  115127600
# 2017-01-04  28.962500  29.127501  28.937500  29.004999  27.227135   84472400
# 2017-01-05  28.980000  29.215000  28.952499  29.152500  27.365593   88774400
# 2017-01-06  29.195000  29.540001  29.117500  29.477501  27.670671  127007600
# 2017-01-09  29.487499  29.857500  29.485001  29.747499  27.924126  134247600
# ......

# 多股
data = yf.download("SPY AAPL", start="2017-01-01", end="2017-04-30",
                   group_by="ticker")
#                  AAPL                                   ...         SPY
#                  Open       High        Low      Close  ...         Low       Close   Adj Close     Volume
# Date                                                    ...
# 2017-01-03  28.950001  29.082500  28.690001  29.037500  ...  223.880005  225.240005  205.509079   91366500
# 2017-01-04  28.962500  29.127501  28.937500  29.004999  ...  225.610001  226.580002  206.731735   78744400
# 2017-01-05  28.980000  29.215000  28.952499  29.152500  ...  225.479996  226.399994  206.567459   78379000
# 2017-01-06  29.195000  29.540001  29.117500  29.477501  ...  225.899994  227.210007  207.306549   71559900
# ......

默认是获取天级别的数据,如果你需要获取分钟级的,只需要添加interval参数:

import yfinance as yf

# 单股
data = yf.download("AAPL", start="2022-05-18", end="2022-05-23", interval="1m")
print(data)

#                                  Open        High         Low       Close   Adj Close   Volume
# Datetime
# 2022-05-17 12:00:00-04:00  148.000000  148.050003  147.839996  147.865005  147.865005        0
# 2022-05-17 12:01:00-04:00  147.869507  147.919998  147.779999  147.889893  147.889893   123746
# 2022-05-17 12:02:00-04:00  147.889999  147.929993  147.750000  147.907394  147.907394    92847
# 2022-05-17 12:03:00-04:00  147.904999  147.929993  147.785004  147.839996  147.839996    79266
# 2022-05-17 12:04:00-04:00  147.839996  147.895004  147.779999  147.860001  147.860001    58905
# ......

它支持的分钟级参数有:1m,2m,5m,15m,30m,60m,90m等等

此外还支持小时级和天线、周线、月线级别:1h,1d,5d,1wk,1mo,3mo等等

获取到的数据类型就是Dataframe,因此你还可以直接保存为csv文件:

# 公众号:Python 实用宝典
import yfinance as yf

data = yf.download("AAPL", start="2022-05-18", end="2022-05-23", interval="1m")
data.to_csv("aapl_20220518_20220523.csv")
# 保存到本地,命名为 aapl_20220518_20220523.csv

3.通过yfinance获取股票基本数据

如果你需要获取一只股票的基本数据,如市值、市盈率、股息等,你可以通过定义一只股票的Ticker,利用其info属性获取:

# 公众号:Python 实用宝典
import yfinance as yf

aapl = yf.Ticker("aapl")
print(aapl.info)
# {'zip': '95014', 'sector': 'Technology', 'fullTimeEmployees': 154000, 'longBusinessSummary': 'Apple ......

这个字典比较长,这里省略显示了,里面包含了比如市盈率(PE)等信息:

# 公众号:Python 实用宝典
import yfinance as yf

aapl = yf.Ticker("aapl")
aapl.info['forwardPE']
# 20.974085

你还可以获取每次派息数据:

# 公众号:Python 实用宝典
import yfinance as yf

aapl = yf.Ticker("aapl")
print(aapl.dividends)
# Date
# 1987-05-11    0.000536
# 1987-08-10    0.000536
# 1987-11-17    0.000714
# 1988-02-12    0.000714
# 1988-05-16    0.000714
#                 ...
# 2021-05-07    0.220000
# ...             ...

获取资产负债表:

# 公众号:Python 实用宝典
import yfinance as yf

aapl = yf.Ticker("aapl")
print(aapl.balancesheet)
#                              2021-09-25    2020-09-26    2019-09-28    2018-09-29
# Total Liab                 2.879120e+11  2.585490e+11  2.480280e+11  2.585780e+11
# Total Stockholder Equity   6.309000e+10  6.533900e+10  9.048800e+10  1.071470e+11
# Other Current Liab         5.357700e+10  4.786700e+10  4.324200e+10  3.929300e+10
# Total Assets               3.510020e+11  3.238880e+11  3.385160e+11  3.657250e+11
# Common Stock               5.736500e+10  5.077900e+10  4.517400e+10  4.020100e+10
# ......

现金流数据:

# 公众号:Python 实用宝典
import yfinance as yf

aapl = yf.Ticker("aapl")
print(aapl.cashflow)
#                                              2021-09-25    2020-09-26    2019-09-28    2018-09-29
# Investments                               -2.819000e+09  5.335000e+09  5.809300e+10  3.084500e+10
# Change To Liabilities                      1.400200e+10 -1.981000e+09 -2.548000e+09  9.172000e+09
# Total Cashflows From Investing Activities -1.454500e+10 -4.289000e+09  4.589600e+10  1.606600e+10
# ......

新闻数据:

# 公众号:Python 实用宝典
import yfinance as yf

aapl = yf.Ticker("aapl")
print(aapl.news)
# [{'uuid': '476a41c6-c6dc-3050-9b8f-c3777c8485b2', 'title': "Dow Jones Futures Rise After 'Hard' Reality Hits Market; What To Do Now", 'publisher': "Investor's Business Daily", 
# 'link': 'https://finance.yahoo.com/m/476a41c6-c6dc-3050-9b8f-c3777c8485b2/dow-jones-futures-rise-after.html', 
# 'providerPublishTime': 1653305573, 'type': 'STORY'}, {'uuid': '721d466d-5394-3f3c-a9c3-b0920d44c7f3' ......

总之,有了yfinance这个神器,除了高频数据你无法获取之外,其他的美股数据你都能获取得到,有需要的小伙伴可以试试,非常好用。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

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

Python 通过阿里云日志服务上传日志并监控告警

在我们的日常生活工作中,经常会遇到需要上传日志的场景,比如多台机器运行同一个程序,并且需要记录每台机器程序产生的日志,根据相关关键词告警,或者进行无数据告警,如果自己搭建这套系统需要耗费不少时间,因此如果能使用市面上现成的系统会很方便。

本文将教你如何通过阿里云日志服务搭建一套通过Python上传日志、配置日志告警的监控服务。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install aliyun-log-python-sdk

接下来,登陆阿里云控制台,进入日志应用,通过下面的步骤创建日志Project和Logstore:

点击Python – SDK 写入,再根据你的需要创建Project和Logstore:

随后会进入这个页面,直接点击确定即可:

2.使用阿里云SDK上传Python日志

为了使用阿里云SDK上传日志,我们需要先获取Access Token, 将鼠标移动到右上角头像上点击AccessKey管理:

然后点击创建AccessKey,输入相关验证信息就能获取 accessKeyId 和 accessKey:

编写Python代码,配置AccessKey和你在第一步骤创建的Project及logstore名称:

from aliyun.log import LogClient, PutLogsRequest, LogItem, GetLogsRequest, IndexConfig
import time

# 配置AccessKey、服务入口、Project名称、Logstore名称等相关信息。
# 阿里云访问密钥AccessKey。更多信息,请参见访问密钥。
# 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维。
accessKeyId = "你的AccessKey ID"
accessKey = "你的AccessKey"
# 日志服务的域名。更多信息,请参见服务入口。此处以广州为例,其它地域请根据实际情况填写。
endpoint = "cn-guangzhou.log.aliyuncs.com"

# 创建日志服务Client。
client = LogClient(endpoint, accessKeyId, accessKey)

# Project名称。
project_name = "aliyun-test-project"
#Logstore名称
logstore_name = "aliyun-test-logstore"
# 查询语句。
query = "*| select dev,id from " + logstore_name
# from_time和to_time表示查询日志的时间范围,Unix时间戳格式。
from_time = int(time.time()) - 3600
to_time = time.time() + 3600

然后我们就可以编写Python代码创建索引(日志的索引可以理解为MySQL中的数据库)和插入日志了:

# 向Logstore写入数据。
def put_logs():
    print("ready to put logs for %s" % logstore_name)
    log_group = []
    for i in range(0, 100):
        log_item = LogItem()
        contents = [
            ('dev', 'test_put'),
            ('id', str(i))
        ]
        log_item.set_contents(contents)
        log_group.append(log_item)
    request = PutLogsRequest(project_name, logstore_name, "", "", log_group, compress=False)
    client.put_logs(request)
    print("put logs for %s success " % logstore_name)
    time.sleep(5)

if __name__ == '__main__':
    # 向Logstore写入数据。
    put_logs()

运行程序后出现对应的提示,说明日志上传成功:

python test.py
# ready to put logs for tradingview
# put logs for tradingview success 

进入控制台对应的Project,你会看到刚刚上传的日志已经显示在上面:

3.配置日志告警

日志告警的配置也非常简单,输入你的查询条件,获得输出后点击上方另存为告警:

在查询统计中添加你需要监控并触发告警的条件,比如我设置出现一次该日志的时候触发告警:

效果如下,我这里文本配置得太简单了,你也可以在标注中配置复杂一点的文本:

用起来挺方便的,如果你有类似的多机器日志监控服务,比如分布式模型训练监控、交易服务监控等等,可以考虑使用这个日志服务。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

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

Python Pyintervals 解决你的阈值判断问题

Pyintervals 是一个用于数值区间计算的模块,比如我们想要判断一个数值是否处于一个、或者一系列区间范围内,就可以使用Pyintervals模块取缔IF-ELSE语句以达到简化代码的目的。

如果你想一次性生成上千个区间阈值并进行数值区间判断,比如根据数值生成成百上千个分类,那么这个模块就是你的最佳选择。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install pyinterval

2.Pyintervals 使用方法

使用Pyinterval做区间和阈值判断是非常简单的:

from interval import interval
a = interval[1,5]
# interval([1.0, 5.0])
print(3 in a)
# True

此外,你还可以构建一个多区间:

from interval import interval
a = interval([0, 1], [2, 3], [10, 15])
print(2.5 in a)
# True

interval.hall 方法还可以将多个区间合并,取其最小及最大值为边界:

from interval import interval
a = interval.hull((interval[1, 3], interval[10, 15], interval[16, 2222]))
# interval([1.0, 2222.0])
print(1231 in a)
# True

区间并集计算:

from interval import interval
a = interval.union([interval([1, 3], [4, 6]), interval([2, 5], 9)])
# interval([1.0, 6.0], [9.0])
print(5 in a)
# True
print(8 in a)
# False

3.生成多个阈值区间

如果你在做深度学习训练分类任务,你的分类数量比较多,达到了上百个,请不要傻傻地使用IF-ELSE, 下面教你使用四行代码生成上百个阈值区间。

假设你的值区间分布在0,1之间,每个阈值范围为0.005,并有正负两个方向。下面这4行代码就能非常简单地实现你想要的区间阈值:

from interval import interval
import numpy as np
threshold_list = np.arange(0.0, 1.0, 0.005)
intervals = [interval([threshold_list[i - 1], threshold_list[i]]) for i in range(1, len(threshold_list))]
intervals += [interval([-threshold_list[i], -threshold_list[i - 1]]) for i in range(len(threshold_list) - 1, 0, -1)]
print(len(intervals))
# 398
print(intervals[0], intervals[-1])
# interval([0.0, 0.005]) interval([-0.005, -0.0])

有了这个阈值,区间,你想要画分类就非常简单了,下面是一个简单示例,实际工作中要因不同应用场景改变使用方式。

target = 0.023
class_labels = {}
for index, interval_ in enumerate(intervals):
    if target in interval_:
        class_labels[target] = index

Pyintervals对于正在做大规模分类任务的同学而言是非常好用的模块,建议有需要的朋友可以试一试。其他同学也可以收藏点赞记录一下,说不定未来也会有应用场景呢!

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

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

Tsmoothie 这个神奇的Python库,可以将数据平滑化并找到异常点

在处理数据的时候,我们经常会遇到一些非连续的散点时间序列数据:

有些时候,这样的散点数据是不利于我们进行数据的聚类和预测的。因此我们需要把它们平滑化,如下图所示:

将散点都去除,平滑后的效果如下:

​这样的时序数据是不是看起来舒服多了?​此外,使用平滑后的时序数据去做聚类或预测或许有令人惊艳的效果,因为它去除了一些偏差值并细化了数据的分布范围。

如果我们自己开发一个这样的平滑工具,会耗费不少的时间。​因为平滑的技术有很多种,你需要一个个地去研究,找到最合适的技术并编写代码,这是一个非常耗时的过程。平滑技术包括但不限于:

  • 指数平滑
  • 具有各种窗口类型(常数、汉宁、汉明、巴特利特、布莱克曼)的卷积平滑
  • 傅立叶变换的频谱平滑
  • 多项式平滑
  • 各种样条平滑(线性、三次、自然三次)
  • 高斯平滑
  • 二进制平滑

所幸,有大佬已经为我们实现好了时间序列的这些平滑技术,并在GitHub上开源了这份模块的代码——它就是 tsmoothie。

下面就让我们来试一下 tsmoothie.

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install tsmoothie

PS, Tsmoothie仅支持Python 3.6 及以上的版本。

2.Tsmoothie 基本使用

为了尝试Tsmoothie的效果,我们需要生成随机数据:

import numpy as np
import matplotlib.pyplot as plt
from tsmoothie.utils_func import sim_randomwalk
from tsmoothie.smoother import LowessSmoother

# 生成 3 个长度为200的随机数据组
np.random.seed(123)
data = sim_randomwalk(n_series=3, timesteps=200, 
                      process_noise=10, measure_noise=30)

然后使用Tsmoothie执行平滑化:

# 平滑
smoother = LowessSmoother(smooth_fraction=0.1, iterations=1)
smoother.smooth(data)

通过 smoother.smooth_data 你就可以获取平滑后的数据:

print(smoother.smooth_data)
# [[   5.21462928    3.07898076    0.93933646   -1.19847767   -3.32294934 
#     -5.40678762   -7.42425709   -9.36150892  -11.23591897  -13.05271523 
#      .......       .......       .......      .......       .......   ]]

绘制效果图:

# 生成范围区间
low, up = smoother.get_intervals('prediction_interval')

plt.figure(figsize=(18,5))

for i in range(3):
    
    plt.subplot(1,3,i+1)
    plt.plot(smoother.smooth_data[i], linewidth=3, color='blue')
    plt.plot(smoother.data[i], '.k')
    plt.title(f"timeseries {i+1}"); plt.xlabel('time')

    plt.fill_between(range(len(smoother.data[i])), low[i], up[i], alpha=0.3)

3.基于Tsmoothie的极端异常值检测

事实上,基于smoother生成的范围区域,我们可以进行异常值的检测:

可以看到,在蓝色范围以外的点,都属于异常值。我们可以轻易地将这些异常值标红或记录,以便后续的处理。

_low, _up = smoother.get_intervals('sigma_interval', n_sigma=2)
series['low'] = np.hstack([series['low'], _low[:,[-1]]])
series['up'] = np.hstack([series['up'], _up[:,[-1]]])
is_anomaly = np.logical_or(
    series['original'][:,-1] > series['up'][:,-1], 
    series['original'][:,-1] < series['low'][:,-1]
).reshape(-1,1)

假设蓝色范围interval的最大值为up、最小值为low,如果存在 data > up 或 data < low 则表明此数据是异常点。

使用以下代码通过滚动数据点进行平滑化和异常检测,就能保存得到上方的GIF动图。

# https://github.com/cerlymarco/MEDIUM_NoteBook/blob/master/Anomaly_Detection_RealTime/Anomaly_Detection_RealTime.ipynb

import numpy as np
import matplotlib.pyplot as plt
from celluloid import Camera
from collections import defaultdict
from functools import partial
from tqdm import tqdm

from tsmoothie.utils_func import sim_randomwalk, sim_seasonal_data
from tsmoothie.smoother import *


def plot_history(ax, i, is_anomaly, window_len, color='blue', **pltargs):
    
    posrange = np.arange(0,i)
    
    ax.fill_between(posrange[window_len:], 
                    pltargs['low'][1:], pltargs['up'][1:], 
                    color=color, alpha=0.2)
    if is_anomaly:
        ax.scatter(i-1, pltargs['original'][-1], c='red')
    else:
        ax.scatter(i-1, pltargs['original'][-1], c='black')
    ax.scatter(i-1, pltargs['smooth'][-1], c=color)
    
    ax.plot(posrange, pltargs['original'][1:], '.k')
    ax.plot(posrange[window_len:], 
            pltargs['smooth'][1:], color=color, linewidth=3)
    
    if 'ano_id' in pltargs.keys():
        if pltargs['ano_id'].sum()>0:
            not_zeros = pltargs['ano_id'][pltargs['ano_id']!=0] -1
            ax.scatter(not_zeros, pltargs['original'][1:][not_zeros], 
                       c='red', alpha=1.)

np.random.seed(42)

n_series, timesteps = 3, 200

data = sim_randomwalk(n_series=n_series, timesteps=timesteps, 
                      process_noise=10, measure_noise=30)

window_len = 20

fig = plt.figure(figsize=(18,10))
camera = Camera(fig)

axes = [plt.subplot(n_series,1,ax+1) for ax in range(n_series)]
series = defaultdict(partial(np.ndarray, shape=(n_series,1), dtype='float32'))

for i in tqdm(range(timesteps+1), total=(timesteps+1)):
    
    if i>window_len:
    
        smoother = ConvolutionSmoother(window_len=window_len, window_type='ones')
        smoother.smooth(series['original'][:,-window_len:])

        series['smooth'] = np.hstack([series['smooth'], smoother.smooth_data[:,[-1]]]) 

        _low, _up = smoother.get_intervals('sigma_interval', n_sigma=2)
        series['low'] = np.hstack([series['low'], _low[:,[-1]]])
        series['up'] = np.hstack([series['up'], _up[:,[-1]]])

        is_anomaly = np.logical_or(
            series['original'][:,-1] > series['up'][:,-1], 
            series['original'][:,-1] < series['low'][:,-1]
        ).reshape(-1,1)
        
        if is_anomaly.any():
            series['ano_id'] = np.hstack([series['ano_id'], is_anomaly*i]).astype(int)
            
        for s in range(n_series):
            pltargs = {k:v[s,:] for k,v in series.items()}
            plot_history(axes[s], i, is_anomaly[s], window_len, 
                         **pltargs)

        camera.snap()
        
    if i>=timesteps:
        continue
    
    series['original'] = np.hstack([series['original'], data[:,[i]]])

    
print('CREATING GIF...')  # it may take a few seconds
camera._photos = [camera._photos[-1]] + camera._photos
animation = camera.animate()
animation.save('animation1.gif', codec="gif", writer='imagemagick')
plt.close(fig)
print('DONE')

注意,异常点并非都是负面作用,在不同的应用场景下,它们可能代表了不同的意义。

比如在股票中,它或许可以代表着震荡行情中某种趋势反转的信号。

或者在家庭用电量分析中,它可能代表着某个时刻的用电峰值,根据这个峰值我们可以此时此刻开启了什么样的电器。

所以异常点的作用需要根据不同应用场景进行不同的分析,才能找到它真正的价值。

总而言之,Tsmoothie 不仅可以使用多种平滑技术平滑化我们的时序数据,还可以根据平滑结果找出数据中的离群点,是我们做数据分析和研究的一个好帮手,非常有价值。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

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

超美!教你用 Python 拍摄游戏延时摄影

为什么要拍摄游戏延时摄影?这个时代,随着游戏引擎技术的快速发展,游戏画面越来越精美,许多人迷上了游戏内的角色、场景。尤其是端游,显卡技术能够支撑精美的游戏画面,最有名的莫过于《地平线》系列游戏。

很多玩家希望拍摄这些精美游戏中的画面,尤其是希望能拍摄到游戏内不同时刻的画面,为了满足这个需求,我们就需要用上延时摄影。游戏内的时间过得比现实世界更快,一个小时内可能你就能经历白天的夜晚的变化,这也为延时摄影提供了很好的环境。

那么究竟怎么在拍摄中实现延时的效果呢?方法大致有两种,最简单的可以先录制视频,然后用后期剪辑软件或者特效软件通过丢帧的方法实现,但这样一来便造成了巨大的浪费。拍几个小时的视频,如果通过丢帧实现延时效果,最后转换为几十分钟的片段,那么被丢掉的帧就要比最后留下的多得多。如果要实现更高速的画面运动,这种浪费无疑将会被更加扩大。

本篇教程介绍第二种方法,定时截图的形式,我们将结合前面Python实用宝典使用过的三个模块——moviepy、win32gui 及 PIL 为大家讲解如何使用Python在游戏中实现延时摄影,我还将教你如何将图片拼接成视频、添加背景音乐一条龙操作。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install moviepy
pip install pypiwin32
pip install pillow

本文所有代码均开源在:https://github.com/Ckend/python-time-lapse-photo 仓库,如果你无法访问GitHub,也可以在Python实用宝典后台回复 延时摄影 下载。

2.游戏延时摄影—定时”拍摄”

为了实现定时拍摄的逻辑,我们需要用到pypiwin32模块和pillow模块,在之前的这篇文章中有介绍过:

超方便的 Python 唤醒窗口自动截图脚本

分为三个步骤:

1. 获得游戏窗口界面

2. 获得游戏界面大小

3. 截图

每隔N秒定时循环执行以上三个步骤,代码如下:

# main.py
# Python实用宝典
# 2022-03-25
import time
import win32gui
from PIL import ImageGrab


def get_window_pos(name):
    name = name
    handle = win32gui.FindWindow(0, name)
    if handle == 0:
        return None
    else:
        return win32gui.GetWindowRect(handle), handle

while True:
    try:
        (x1, y1, x2, y2), handle = get_window_pos('极限竞速:地平线 4')
        win32gui.SetForegroundWindow(handle)
        img_ready = ImageGrab.grab((x1, y1, x2, y2))
        img_ready.save(f"./result/{time.time()}.jpg")
        time.sleep(5)
    except Exception as e:
        print(e)

请注意,”极限竞速:地平线 4″ 要改成你对应拍摄的游戏名称,这样,运行程序后就会自动在result文件夹下定时生成截图:

成功截取你想要的时间段的场景图片后,就可以进行下面的拼接和补充背景音乐部分。

3.拼接延时摄影视频

为了达到延时摄影的效果,我们在这一部分中将使用moviepy模块,拼接所有图片到一个视频中。

当然还要补充背景音乐,代码其实非常简单:

# jointer.py
# Python实用宝典
# 2022-03-25
import os
import moviepy
import moviepy.video.io.ImageSequenceClip
from moviepy.editor import *

def pics2video(frames_dir, video_dst, music, fps=10):
    """
    图片合成MP4

    Args:
        frames_dir (str): 图片目录
        video_dst (str): 目标目录
        fps (int, optional): 帧数. Defaults to 25.
    """
    frames_name = sorted(os.listdir(frames_dir))
    frames_path = [frames_dir+frame_name for frame_name in frames_name]
    clip = moviepy.video.io.ImageSequenceClip.ImageSequenceClip(frames_path, fps=fps)
    
    audio_clip = AudioFileClip(music).volumex(0.5)
    audio = afx.audio_loop( audio_clip, duration=clip.duration)
    final_video = clip.set_audio(audio)

    final_video.write_videofile(video_dst, codec='libx264')

music = '打上花火.mp3'
frames_dir = './result/'
video_dst = 'screenshots.mp4'
pics2video(frames_dir, video_dst, music)

1.将你的音乐放在当前目录下,修改music变量为对应的文件名。

2.调整你想要的fps参数—帧数,这个值越低,画面越顺畅。

运行此文件后就会在当前文件夹下生成 ‘screenshots.mp4’. 这个就是我们的处理结果了,双击打开试试吧。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

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

超级安全!Python Pillow合成多张图片到PDF格式

在日常生活中,经常会遇到需要提交身份证正反面证明资料的情况,而且这些网站大部分只接受pdf格式,这时候我们就需要把身份证正反面两张图片合成为一个pdf文件。

在macOS系统下,预览软件可以轻松做到这一点,同时打开图片到一个预览窗口下,点击导出PDF就能成功导出。但是Windows系统就没有这么方便的软件可以实现这一点,网上有很多合成PDF的网站,但是这些网站无一例外需要上传PDF进行合成,个人认为非常地不安全。

因此,最安全的方法,还是我们自己写一个Python脚本实现合成功能。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install pillow

2.Pillow 合成PDF原理

Pillow模块,即PIL:Python Imaging Library,已经是Python平台事实上的图像处理标准库了。PIL功能非常强大,但API却非常简单易用。通过它,我们能很轻松地操作图像,并导出为不同格式。

首先来一个简单的示例,我们将打开一张图片,并将其保存为pdf格式:

from PIL import Image
import os


def convert_img_pdf(filepath, output_path):
    """
    转换图片为pdf格式

    Args:
        filepath (str): 文件路径
        output_path (str): 输出路径
    """
    output = Image.open(filepath)
    output.save(output_path, "pdf", save_all=True)
    
    
if __name__ == "__main__":
    convert_img_pdf("1.jpeg", "./test.pdf")

随便使用一张图片测试一下:

在运行代码后,它便成功地转化为了PDF文件:

几行代码便完成了这个转换,这个可比那些把照片上传到云端的网站安全多了。

3.多张照片合成PDF

有了前面照片转化PDF的基础知识,想要理解下面的多图合成PDF的代码就非常简单了。

其实就是使用了.save的一个特殊参数 append_images:

output.save(pdfFilePath, "pdf", save_all=True, append_images=sources)

通过把图片都存入到一个”sources”数组中,我们就能很轻易地合成这些图像到PDF中。

from PIL import Image
import os

def combine_imgs_pdf(folder_path, pdf_file_path):
    """
    合成文件夹下的所有图片为pdf

    Args:
        folder_path (str): 源文件夹
        pdf_file_path (str): 输出路径
    """
    files = os.listdir(folder_path)
    png_files = []
    sources = []
    for file in files:
        if 'png' in file or 'jpg' in file:
            png_files.append(folder_path + file)
    png_files.sort()

    output = Image.open(png_files[0])
    png_files.pop(0)
    for file in png_files:
        png_file = Image.open(file)
        if png_file.mode == "RGB":
            png_file = png_file.convert("RGB")
        sources.append(png_file)
    output.save(pdf_file_path, "pdf", save_all=True, append_images=sources)

if __name__ == "__main__":
    folder = r"G:\证件\\"
    pdfFile = r"G:\证件\身份证.pdf"
    combine_imgs_pdf(folder, pdfFile)

这样,只要将你的证件照都放在一个文件夹中,运行这个Python代码,它就能自动将这些证件合成到一个PDF中,并输出到你指定的路径。非常简单方便。

有需要的小伙伴,刚开那这份代码去试一下吧!在Python实用宝典后台回复 合成pdf 就能下载啦!

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

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