TowardsDataScience 博客中文翻译 2020(九百五十一)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

使用 python 包构建您的自定义数据集— MLDatasetBuilder

原文:https://towardsdatascience.com/using-python-package-to-build-your-custom-dataset-mldatasetbuilder-d23ffd6d4fd1?source=collection_archive---------40-----------------------

MLDatasetBuilder 是一个 python 包,可帮助您为 ML 数据集准备图像。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源于【www.spritle.com】

作为一名 ML 新手,我需要找出为我们的机器学习训练模型准备数据集的最佳方法。根据我的上一篇文章,我为这个过程设计了一个 Python 包!

每当您训练自定义模型时,重要的是数据集。是的,当然,数据集在深度学习中起主要作用。模型的准确性将取决于数据集。因此,在训练自定义模型之前,您需要计划如何构建数据集?在这里,我将分享我关于构建数据集的简单方法的想法。

** [## MLDatasetBuilder

MLDatasetBuilder 是一个 python 包,可帮助您为 ML 数据集准备图像。每当我们启动一台机器…

pypi.org](https://pypi.org/project/MLDatasetBuilder/)

MLDatasetBuilder-版本 1.0.0

为机器学习构建数据集的 Python 包

每当我们开始一个机器学习项目时,我们首先需要的是一个数据集。数据集将是训练模型的支柱。您可以自动或手动构建数据集。MLDatasetBuilder 是一个 python 包,可帮助您为 ML 数据集准备图像。

[## karthick 965938/ML-数据集构建器

MLDatasetBuilder 是一个 python 包,可帮助您为 ML 数据集准备图像。每当我们启动一台机器…

github.com](https://github.com/karthick965938/ML-Dataset-Builder)

装置

我们可以使用下面的命令安装MLDatasetBuilder

pip install MLDatasetBuilder

如何测试

当您在终端中运行python3时,它将产生如下输出:

Python 3.6.9 (default, Apr 18 2020, 01:56:04) 
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 

运行下面的代码可以得到 MLDatasetBuilder 包的初始化过程输出。**

>>> from MLDatasetBuilder import *
>>> MLDatasetBuilder()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

初始化过程的输出

可用操作

准备图像移除不需要的格式图像,并重命名您的图像

#PrepareImage(folder_name, image_name)
**PrepareImage('images', 'dog')**

提取图像视频文件中提取图像

#ExtractImages(video_path, file_name, frame_size)
**ExtractImages('video.mp4', 'frame', 10)**
#OR
#ExtractImages(video_path, filename)
**ExtractImages('video.mp4', 'frame')**
#Default FPS will be 5

第一步——从谷歌获取图片

是的,我们可以从谷歌上获取图片。使用下载所有图像浏览器扩展,我们可以在几分钟内轻松获取图像。你可以查看这里关于这个扩展的更多细节!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从谷歌获取图片

步骤 2-创建 Python 文件

一旦你使用这个扩展下载了图像,你就可以创建一个名为 test.py 的 python 文件,目录如下。

download_image_folder/
|   _14e839ba-9691-11ea-a968-2ed746e9a968.jpg
|   5e5f7af12600004018b602c0.jpeg
|   A471529_Alice_b-1.jpg
|   image1.png
|   image2.png
|   ...
test.py

在 images 文件夹中,你可以看到许多 PNG 图像和随机文件名。

步骤 3 —准备图像

MLDatasetBuilder*提供了一个名为 **PrepareImage 的方法。*使用此方法,我们可以删除不想要的图像,并重命名您已经从浏览器的扩展下载的图像文件。

*PrepareImage(folder_path, class_name)
#PrepareImage('download_image_folder', 'dog')*

根据上面的代码,我们需要提到图像文件夹路径类名

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

准备图像选项的输出

完成这个过程后,你的图像文件夹结构将如下所示

*download_image_folder/
|   dog_0.jpg
|   dog_1.jpg
|   dog_2.jpg
|   dog_3.png
|   dog_4.png
|   ...
test.py*

这个过程非常有助于在贴标签的同时给你的图像添加注释。当然,这将是标准化的事情之一。

步骤 4 —提取图像

MLDatasetBuilder还提供了一个名为**的提取图像的方法。使用这种方法我们可以从视频文件中提取图像。****

**download_image_folder/
video.mp4
test.py**

根据下面的代码,我们需要提到视频路径、文件夹名称、帧大小。文件夹名类名framesize 的设为默认值 5 并且不是强制的**。**

**ExtractImages(video_path, folder_name, framesize)
#ExtractImages('video.mp4', 'frame', 10)
ExtractImages(video_path, folder_name)
#ExtractImages('video.mp4', 'frame')**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

提取图像方法的输出

完成这个过程后,你的图像文件夹结构将如下所示

**download_image_folder/
dog/
|   dog_0.jpg
|   dog_1.jpg
|   dog_2.jpg
|   dog_3.png
|   dog_4.png
|   ...
dog.mp4
test.py**

什么是 2.0.0 版?

我计划在下个月发布 2.0.0 版本,这将包括一些额外的功能。

我的意思是这个包将提供超过 100 个带有注释文件的物体图片:)

贡献的

欢迎所有问题和拉请求!要在本地运行代码,首先,派生存储库,然后在您的计算机上运行以下命令:

**git clone https://github.com/<your-username>/ML-Dataset-Builder.git
cd ML-Dataset-Builder
# Recommended creating a virtual environment before the next step
pip3 install -r requirements.txt**

添加代码时,一定要在必要的地方编写单元测试。

接触

MLDatasetBuilder 是由 Karthick Nagarajan 创建的。请随时在TwitterLinkedin 或通过电子邮件联系我们!

原载于www.spritle.com**

用 Python & Stan 用一个不切实际的模型选出超级碗冠军

原文:https://towardsdatascience.com/using-python-stan-to-pick-the-superbowl-winner-with-an-unrealistic-model-e68c84c3e95a?source=collection_archive---------25-----------------------

贝叶斯逻辑回归的一个简单例子

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

戴夫·阿达姆松在 Unsplash 上拍摄的照片

本文将说明一种使用 Stan 构建简单、不切实际但有用的概率模型的方法,以:

  • 根据球队进攻、对手防守以及球队是否在主场比赛,预测每支 NFL 球队在一场比赛中的得分。
  • 使用该模型模拟一个时间表,其中每支球队与所有 31 支球队进行 100 次主客场比赛。
  • 使用结果为所有 32 个团队生成一个实力排名。
  • 使用该模型预测季后赛的结果&最终是超级碗。

原定目标

我本来是想找一个小问题,学习如何使用 Stan 进行贝叶斯建模。NFL 权力排名模型似乎是一个有趣的尝试。某一年的数据样本量很小,因此很有吸引力:

  • 32 支队伍
  • 16 场比赛
  • 512 种结果——每场比赛每队一种
  • 随着新分数的出现,该模型可以每周更新。

从斯坦的主页——https://mc-stan.org/——可以下载该软件。

关于斯坦

“Stan 是用于统计建模和高性能统计计算的一流平台。成千上万的用户依赖 Stan 进行社会、生物、物理科学、工程和商业领域的统计建模、数据分析和预测。

用户在 Stan 的概率编程语言中指定对数密度函数,得到:

  • 使用 MCMC 抽样的完全贝叶斯统计推断(NUTS,HMC)
  • 带有变分推理的近似贝叶斯推理
  • 优化的惩罚最大似然估计(L-BFGS)”

数据

数据很容易从 https://www.pro-football-reference.com/years/2019/games.htm 获得。只需单击共享箭头选项卡,即可获得要复制的数据的 csv 布局。

为了保持模型简单,模型需要的字段是:

  • 获胜队
  • 失败的队伍
  • 获胜团队得分
  • 失去团队分数
  • 主/从指示器—>@

不切实际的分数概率模型

在实际比赛中,得分事件产生 1、2、3 或 6 分,并且是 3 个以上因素的结果。

将被评估的模型将把分数仅仅作为球队进攻、对手防守以及球队是否在主场比赛的函数。

用来预测球队得分的不切实际的模型是:

  • 一个队可以得 0 到 60 分
  • 团队得分的点数被建模为具有 60 次试验的二项式分布,并且成功概率 p 如上所述被估计。

将使用 Pystan 对模型进行估计,并对模型中的特征进行先验分布,如下所述。

数据处理

抱歉——为读到这篇文章的任何数据科学家争论——我道歉。

进口:

import pandas as pd
import numpy as np
import pystan
from   pystan import StanModel

(1)读入保存的结果和重命名列的 csv 文件:

df         = pd.read_csv("~/ml/Data/NFL2019.csv")df.columns = ['Week', 'Day', 'Date', 'Time', 'Winner',    'away','Loser','Unnamed: 7', 'PtsW', 'PtsL', 'YdsW', 'TOW', 'YdsL', 'TOL']

(2)建立将城市队名称映射到队名称和队 id 的字典。最初,我认为我必须构建一个 256 X 65 X 的设计矩阵,因此团队 id 在下面的代码中是 col_id。稍后会详细介绍。

如果 col_id 没有从 1 开始,问题可能会在以后出现,因为 Stan 默认从 1 而不是 0 开始。

team_dict = {}
col_id    = 1for i in range(df.shape[0]):
    team_ = df.Winner[i]
    temp  = team_.split()
    temp  = temp[-1]
    if team_ not in team_dict:
        team_dict[team_] = dict(team=temp,k= col_id,)
        col_id += 1

带有 k 的前几个 team_dict 条目是 team_id:

{'Green Bay Packers': {'team': 'Packers', 'k': 1},
 'Minnesota Vikings': {'team': 'Vikings', 'k': 2},
 'Los Angeles Rams': {'team': 'Rams', 'k': 3},
 'Baltimore Ravens': {'team': 'Ravens', 'k': 4},
 'Philadelphia Eagles': {'team': 'Eagles', 'k': 5},

(3)构建反向字典,将列 id 映射回团队

X_dict = {}
for key in team_dict:
    x_key = team_dict[key]['team']
    X_dict[x_key] = team_dict[key]['k']

前几个 X_dict 条目:

{'Packers': 1,
 'Vikings': 2,
 'Rams': 3,
 'Ravens': 4,
 'Eagles': 5,

(4)构建 X 矩阵以馈送给 Stan。它将有 3 列:

  • 我们预测其得分的团队的 id
  • 它正在玩的队的 id(防御)
  • 基于数据中@符号的 home 0/1 指示器

此外,存储分数。

对于数据中的每一行,在 X 矩阵中创建两行,一行用于获胜的团队,一行用于失败的团队。idx_o & idx_d 是 team_dict 中攻防队的指数。

这导致在 3 列向量中存储可能非常稀疏的矩阵(在 65 列的每行中只有 3 个非零元素)。

X      = np.zeros((2*df.shape[0],3),int)
score  = np.zeros(2*df.shape[0],int)
row    = 0for i in range(df.shape[0]):
    idx_o    = team_dict[df.Winner[i]]['k']
    idx_d    = team_dict[df.Loser[i]]['k']
    X[row,0] = idx_o                         
    X[row,1] = idx_d
    score[row]     = df.PtsW.values[i]
    if df.away[i] != '@':
        X[row,2] = 1 
    row += 1

    idx_o = team_dict[df.Loser[i]]['k']
    idx_d = team_dict[df.Winner[i]]['k']
    X[row,0] = idx_o
    X[row,1] = idx_d
    score[row]     = df.PtsL.values[i]
    if df.away[i] == '@':
        X[row,2] = 1

x 矩阵的前几行:

array([[ 1, 20,  0],
       [20,  1,  1],
       [ 2, 21,  1],
       [21,  2,  0],
       [ 3, 25,  0],
       [25,  3,  1],

使用 Stan 评估模型

(1)Stan 的数据字典定义—相当简单,告诉 Stan 数据是什么以及有多少行(N)。

datadict  = { 
    'offense'  : X[:,0] ,
    'defense'  : X[:,1],
    'home'     : X[:,2] ,
    'score'    : score,
    'N'        : X.shape[0]
}

(2)定义 Stan 模型——Python 多行字符串。

组件:

  • 数据 —如上面的 datadict 中所定义。
  • 参数 —我们希望 Stan 估计的参数列表。一个用于每个队的进攻和防守,一个用于主场比赛和拦截。主队系数有一个上限。
  • 转换后的参数 —该模型估计 **p 的对数,**我们不切实际的二项式模型中的概率。函数 inv_logit 将登录次数转换成成功的概率(在我们的例子中是 60 次试验中每一次的分数)。
  • 模型— 在模型部分,先验分布与我们正在估计的概率模型(得分)一起指定。
stanCode = """
data {
int N;
int score [N];
int offense [N];
int defense [N];
int home    [N];
}
parameters {
vector      [32]       b_offense;
vector      [32]       b_defense;
real <upper = 0.05>    b_home;
real                   alpha;
}
transformed parameters{
  real mu [N];
  for (n in 1:N){
    mu[n]  <- inv_logit(alpha + b_offense[offense[n]] 
                              + b_defense[defense[n]]
                              + b_home * home[n]);
  }
}model {
alpha      ~ normal(log(23),1);
b_offense  ~ cauchy(0,0.5);
b_defense  ~ cauchy(0,0.5);
b_home     ~ double_exponential(0,5);
score      ~ binomial(60,mu);}
"""

(3)编译 Stan 模型——这需要一些时间。将打印出一条信息消息。

from pystan import StanModel
sm = StanModel(model_code=stanCode)

(4)估计模型系数——op 将是一个字典,包含每个队的进攻和防守系数、主客场系数、截距和预测 mu。

op = sm.optimizing(data=datadict)

实力排名

在这一点上,我们现在已经有了模型权重,它使我们能够通过在游戏中运行 sigmoid 变换,根据任何两个队的进攻和防守系数以及该队是否在主场,来预测他们在游戏中的得分。

我们可以模拟任何球队和其他球队比赛的结果…不限于实际比赛。那么为什么不去做呢?我们模拟了一个时间表,其中每支球队与其他球队“比赛”100 次,50 次在主场,50 次在客场。我们记录赢、输和平局。

首先,我们需要调整索引(team_ids ),因为模拟将在 Python 中进行,并构建一个团队列表来运行模拟。

team_list = []
for team in X_dict:
    team_list.append(team)
    X_dict[team] = X_dict[team] - 1
    print("{a:>20s}  {b:6.3f}  {c:6.3f}".format(
        a=team, 
        b=op['b_offense'][X_dict[team]],
        c=op['b_defense'][X_dict[team]]))

检查前几行——乌鸦和酋长队的进攻系数非常正,防守系数为负,而老鹰队接近平均水平。

 offense  defense
Packers   0.037   -0.203              
Vikings   0.167   -0.226                 
Rams      0.147   -0.131               
Ravens    0.752   -0.358               
Eagles    0.047    0.018                
Bills    -0.252   -0.450               
Chiefs    0.427   -0.226

模拟所有球队之间的 100 场比赛赛季:

wins   = np.zeros(len(team_list),int)
losses = np.zeros(len(team_list),int)
ties   = np.zeros(len(team_list),int)
for idx_1 in range(31):
    for idx_2 in range(idx_1+1,32):
        team_1 = team_list[idx_1]
        team_2 = team_list[idx_2]

        for game in range(100):
            at_home = game % 2 u      = op['alpha'] 
            u     += op['b_offense'][X_dict[team_1]] 
            u     += op['b_defense'][X_dict[team_2]] 
            u     += op['b_home'] * at_home
            prob   = 1\. / (1\. + np.exp(-u))
            pts_1  = np.random.binomial(60,prob) u      = op['alpha'] 
            u     += op['b_offense'][X_dict[team_2]] 
            u     += op['b_defense'][X_dict[team_1]] 
            u     += op['b_home'] * (1 - at_home)
            prob   = 1\. / (1\. + np.exp(-u))
            pts_2  = np.random.binomial(60,prob) if pts_1 > pts_2:
                wins[idx_1]   += 1
                losses[idx_2] += 1
            elif pts_1 < pts_2:
                wins[idx_2]   += 1
                losses[idx_1] += 1
            else:
                ties[idx_1]   += 1
                ties[idx_2]   += 1

结果——按获胜百分比排列的实力等级(平局算作 1/2 的胜负)。

report = pd.DataFrame(dict(
    team = team_list,
    won  = wins,
    lost = losses,
    ties = ties
))
report['winpct'] = np.round((report.won + 0.5 * report.ties) / (report.won + report.lost + report.ties),3)report.sort_values('winpct',ascending=False,inplace=True)
report.reset_index(inplace=True)
report = report[['team','won','lost','ties','winpct']]
print(report)

【2019 赛季模拟实力排名:

这些排名通过了一个意义上的检验——强队在顶部,弱队在底部。大部分球队都在中心,公羊队和牛仔队在排名上表现不佳,而海鹰队和老鹰队表现出色,进入了季后赛。

 team    won  lost  ties  winpct
0       Ravens  3025    53    22   0.979
1     Patriots  2823   230    47   0.918
2        49ers  2795   253    52   0.910
3       Chiefs  2653   379    68   0.867
4       Saints  2460   558    82   0.807
5      Cowboys  2269   726   105   0.749
6      Vikings  2270   735    95   0.748
7         Rams  2104   867   129   0.700
8       Titans  2014   942   144   0.673
9      Packers  1997   979   124   0.664
10    Seahawks  1882  1073   145   0.630
11       Bills  1882  1081   137   0.629
12      Texans  1589  1371   140   0.535
13  Buccaneers  1593  1377   130   0.535
14      Eagles  1585  1366   149   0.535
15    Steelers  1545  1391   164   0.525
16     Falcons  1487  1469   144   0.503
17       Bears  1342  1594   164   0.459
18    Chargers  1297  1666   137   0.440
19       Colts  1237  1716   147   0.423
20      Browns  1213  1739   148   0.415
21     Broncos  1212  1754   134   0.413
22   Cardinals  1032  1922   146   0.356
23       Lions   750  2199   151   0.266
24        Jets   603  2369   128   0.215
25     Raiders   586  2403   111   0.207
26     Jaguars   587  2415    98   0.205
27    Panthers   552  2441   107   0.195
28     Bengals   511  2479   110   0.183
29      Giants   473  2529    98   0.168
30    Redskins   209  2826    65   0.078
31    Dolphins   178  2853    69   0.069

模拟季后赛

用于获取获胜概率的 1 场比赛的函数:

def sim_games(team_1,team_2,row_id,report,s_round,add_home=True):
    wins   = np.zeros(2,int)
    losses = np.zeros(2,int)
    ties   = np.zeros(2,int)
    score  = np.zeros((1000,2),int) for game in range(1000):        
        u      = op['alpha'] 
        u     += op['b_offense'][X_dict[team_1]]   
        u     += op['b_defense'][X_dict[team_2]]  
        u     += op['b_home'] * add_home
        prob   = 1\. / (1\. + np.exp(-u))
        pts_1  = np.random.binomial(60,prob)

        score[game,0] = pts_1 u      = op['alpha'] 
        u     += op['b_offense'][X_dict[team_2]]   
        u     += op['b_defense'][X_dict[team_1]]  
        u     += op['b_home'] * add_home
        prob   = 1\. / (1\. + np.exp(-u))
        pts_2  = np.random.binomial(60,prob)

        score[game,1] = pts_2 if pts_1 > pts_2:
            wins[0]   += 1
            losses[1] += 1
        elif pts_1 < pts_2:
            wins[1]   += 1
            losses[0] += 1
        else:
            ties[0]   += 1
            ties[1]   += 1new_row = pd.DataFrame(dict(
        Round        = s_round,
        Visitor      = team_1,
        V_Wins       = int(wins[0]+ ties[0]/2),
        V_Score      = np.round(np.mean(score[:,0]),1),
        Home         = team_2,
        H_Wins       = int(wins[1]+ ties[1]/2),
        H_Score      = np.round(np.mean(score[:,1]),1)
),index=[row_id])report = pd.concat((report,new_row))
return(report) 

模拟季后赛的函数调用:

进行第一轮比赛,并将预计的获胜者传送到第二轮比赛。

report = pd.DataFrame()
row_id = 0
report = sim_games("Bills","Texans",
row_id,report,s_round='Round 1',add_home=True)
row_id = 1
report = sim_games("Titans","Patriots",
row_id,report,s_round='Round 1',add_home=True)
row_id = 2
report = sim_games("Seahawks","Eagles",
row_id,report,s_round='Round 1',add_home=True)
row_id = 4
report = sim_games("Vikings","Saints",
row_id,report,s_round='Round 1',add_home=True)
row_id = 5
report = sim_games("Bills","Ravens",
row_id,report,s_round='Round 2',add_home=True)
row_id = 6
report = sim_games("Patriots","Chiefs",
row_id,report,s_round='Round 2',add_home=True)
row_id = 7
report = sim_games("Seahawks","49ers",
row_id,report,s_round='Round 2',add_home=True)
row_id = 8
report = sim_games("Saints","Packers",
row_id,report,s_round='Round 2',add_home=True)
row_id = 9
report = sim_games("Saints","49ers",
row_id,report,s_round='Round 3',add_home=True)
row_id = 10
report = sim_games("Patriots","Ravens",
row_id,report,s_round='Round 3',add_home=True)
row_id = 11
report = sim_games("49ers","Ravens",
row_id,report,s_round='superbowl',add_home=False)

结果

 Round   Visitor  V_Wins  V_Score      Home  H_Wins  H_Score
0     Round 1     Bills     648     19.9    Texans     352     17.9
1     Round 1    Titans      77     16.6  Patriots     922     23.9
2     Round 1  Seahawks     685     26.3    Eagles     315     23.5
4     Round 1   Vikings     392     22.9    Saints     607     24.3
5     Round 2     Bills       9     15.4    Ravens     990     27.2
6     Round 2  Patriots     665     22.5    Chiefs     335     20.0
7     Round 2  Seahawks      63     21.3     49ers     936     29.5
8     Round 2    Saints     792     25.1   Packers     207     20.9
9     Round 3    Saints     253     23.2     49ers     746     26.6
10    Round 3  Patriots     233     20.5    Ravens     766     24.3
11  superbowl     49ers     166     24.3    Ravens     834     29.6

总结

2019 年的 NFL 结果被用来建立一个使用 PyStan 预测分数的模型,更重要的是作为一个如何使用 Stan 估计贝叶斯模型的例子。

随着数据的可用和赛季的进展,该模型可用于生成每周电力排名。

一些观察结果:

  • 尽管该模型在权力排名上做得相当好,但预测的分数似乎受到了先验的影响。
  • 具有更大分布的先验可能导致更宽的预测得分范围。
  • 模型的弱点包括模型是基于整个赛季到目前为止,没有额外的重量给予最近的分数,关键的伤病或球员回归。

问题&建议

如果您有任何问题、建议或需要预测模型,请随时发送电子邮件至:

bill.fite@miner3.com。

用 Python 分析《黑色大丽花谋杀案》的残酷歌词

原文:https://towardsdatascience.com/using-python-to-analyze-the-brutal-lyrics-of-the-black-dahlia-murder-with-genius-api-spacy-bfc7e0e8577f?source=collection_archive---------32-----------------------

发现死亡金属的主题

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

UnsplashActionVance 拍照

为什么是黑色大丽花谋杀案?

为了纪念他们即将于 2020 年 4 月 17 日发行的专辑verminus,也因为他们是我有史以来最喜欢的死亡金属乐队之一,我决定分析黑色大丽花谋杀案(BDM)的歌词,看看它们是如何随着时间的推移而演变的。早在 2006 年,我的朋友刻录了一张他最喜欢的金属歌曲的 CD,上面有 BDM 专辑中的“瘴气”。一听到这首歌,我就对生活着了迷,并看过他们五次现场表演。成立于 2001 年,BDM 迅速崛起为最受欢迎的美国死亡金属乐队之一。他们的最后七张专辑随着他们的第五张专辑仪式登上 Billboard 200 排行榜,在 2011 年达到 31 张的峰值!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

https://en . Wikipedia . org/wiki/Ritual _(The _ Black _ Dahlia _ Murder _ album)

主题是黑暗和忧郁的,音乐感觉像是愤怒和抑郁的化身,但作为 21 世纪初一个焦虑的青少年,死亡金属的能量和愤怒引起了我的共鸣。我能感同身受。直到今天,我还能在旋律重复、双踢和抱怨声中找到安慰,因为它们让我处于恍惚状态,让我放松,让我集中注意力。我发现死亡金属是编码和锻炼的完美音乐,我喜欢随着节奏开始我的一天。

获取数据

我正在从 Genius.com 中提取歌词。由于重金属音乐中令人毛骨悚然的尖叫声和神秘的咆哮,歌词有时很难理解。这就是为什么我用天才来破译它们。Genius.com是一个标注歌词、收集音乐、专辑、艺人等琐事的平台。

虽然网站不允许用户使用 API 提取歌词,但我使用的是一个 Genius API 包装器,它用 BeautifulSoup 解析 Genius HTML。这个过程会产生一个熊猫数据帧,其中包含歌曲名称、url、艺术家、专辑和歌词。在我的 GitHub 上一个名为 getLyrics.py 的文件中找到这个包装。

[## 弯曲游戏/歌词-分析

媒体歌词分析。在 GitHub 上创建一个帐户,为 bend game/歌词分析开发做出贡献。

github.com](https://github.com/bendgame/lyrics-analysis)

#import dependencies
from getLyrics import GeniusLyricCollector#pass the api token and artist name into the lyric collector
g = GeniusLyricCollector(token, 'The Black Dahlia Murder')#load the dataframe with the data
songs_df = g.get_artist_songs()#display first 5 rows
songs_df.head()

要使用包装器,将您的 Genius API 令牌和艺术家传递到Genius lyric collector中。然后调用 get_artist_songs() 来填充 DataFrame。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

歌曲 _df 数据帧

探索相册

在分析数据之前,最好根据需要探索和清理数据。马上,我注意到第 2 行没有列出专辑,所以我知道我需要清理数据,我也想添加一些功能。为了保留原始数据帧,以防我需要返回它,我将复制它并在副本上工作。我查看了附带的相册:

lyrics = songs_df[["Lyrics", 'Album', "Title"]].copy()
lyrics.Album.unique()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我只想要他们 8 张录音室专辑里的歌。Verminous 还没有发行,也没有歌词,Black on Black 是一个致敬专辑,而冷血墓志铭是一个 EP,所以我会排除所有这些。

特征工程

特征工程是使用数据挖掘技术和领域知识从原始数据中提取特征的过程。我想设计一些功能,让我深入了解专辑的词汇丰富性。我将使用几个不同的因素来定义词汇丰富性。我再加一个字数唯一字 字数唯一字/字数(词汇多样性)。虽然这是一个有用的度量,并且是一个简单的计算,但是用这种方法计算词汇多样性的基本问题是它对文本长度的敏感性。幸运的是,每张专辑的长度都差不多。已经设计了几种不同的方法来克服方法的问题,但是我将使用简单的计算。

songs_group = lyrics.groupby('Album')
album_stats = pd.DataFrame(columns=('Album', 'word_count', 'unique_count', 'lexical_diversity', 'tokens'))
i = 0
for name, album in songs_group:# Create a list of words for every word that is in an album
    album_tokens = []for lyric in album['Lyrics'].iteritems():if isinstance(lyric[1], str):
            words = lyric[1].replace('\n', ' ')
            words = words.split(' ')album_tokens.extend(words)# Find how many words and unique words are in the album
    unique_count = len(set(album_tokens))
    word_count = len(album_tokens)# Calculate the lexical richness of the album, which is the amount of unique words relative to
    # the total amount of words in the album
    album_stats.loc[i] = (name, word_count, unique_count, (unique_count / float(word_count)), album_tokens)

    i += 1

album_stats["released"] = [2015,2009,2013,2005,2017,2007,2011,2003]
album_stats = album_stats.sort_values('released').reset_index().drop(columns=('index'))
album_stats

我还添加了专辑的发行年份,并按栏目排序。

album_stats["released"] = [2015,2009,2013,2005,2017,2007,2011,2003]
album_stats = album_stats.sort_values('released').reset_index().drop(columns=('index'))
album_stats

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

见识

在 2019 年接受 kerrang.com 采访时,作词人、歌手和乐队主唱 Trevor Strnad 讨论了专辑,将它们从最差到最佳进行了排名。最后,他放了乐队的第二张录音室专辑《T2》中的《瘴气》。伴随着这张专辑长大,我喜欢它,但他说这张专辑感觉没有重点,部分是因为他们从早期的成功和的失败中走得如此之远。统计数据显示, Miasma 拥有最少的单词和最少的独特单词,这表明特雷弗关于主题的观点是正确的,与其他专辑相比,歌词没有那么明确。他没能给予这张专辑应有的关注。

使用 Plotly Express 可视化统计数据

为了可视化数据,我使用了 plotly express ,因为它只用了几行代码就产生了交互式的可视化效果!下面是一个直方图,显示了专辑的字数分布。

#import dependencies
import plotly.express as px#create plot
fig = px.histogram(lyrics, x="word_count", color = 'Album')#show fig
fig.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

箱线图是可视化四分位数统计的好方法。使用 pandas 的 describe() ,也很容易生成原始四分位数。使用 Plotly Express,可以设置盒图中使用的四分位数算法。默认为线性。

#drop songs with no lyrics
lyrics = lyrics.loc[lyrics.word_count > 0]#count words for each song
lyrics['word_count'] = lyrics['Lyrics'].apply(lambda x :  len(x.split()))#count unique words
lyrics['unique_count'] = lyrics['Lyrics'].apply(lambda x: len(set(w for w in x.split())))#calculate lexical diversity
lyrics['lexical_diversity'] = lyrics['unique_count'] / lyrics['word_count']#display the quartile numeric data.
lyrics.describe()fig = px.box(df, x="Album", y="word_count", color = "Album")
fig2 = px.box(lyrics, x="Album", y="unique_count", color = "Album")
fig3 = px.box(lyrics, x="Album", y="lexical_diversity", color = "Album")fig.update_traces(quartilemethod="linear") # or "inclusive", or "exclusive"
fig2.update_traces(quartilemethod="linear") # or "inclusive", or "exclusive"
fig3.update_traces(quartilemethod="linear") # or "inclusive", or "exclusive"fig.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

再一次,我们可以看到专辑《瘴气》没有其他专辑的广度和多样性。看着词汇多样性较低的专辑,我注意到这些都是主题明确的专辑:夜行仪式深渊不被允许的。例如,是他们排行榜上最高的专辑,但词汇多样性比其他专辑低。这可能是因为像“哦,伟大的燃烧的否定者”这样的歌曲有重复的模式,像圣歌,这是专辑的主题。

用空间探索歌词

SpaCy 是一个工业级的自然语言处理库。它是在幕后使用 Cython 开发的,使其快速有效地用于大规模文本处理任务,如词性(PoS)标记和命名实体识别(NER)。我将使用词性标注器来更深入地了解专辑中使用的歌词和主题。

如果你是 spaCy 的新手,我建议你看看他们的安装页面,因为他们有很多安装选项。SpaCy 与 Python 2.7 / 3.5+兼容,可以在 Unix/Linux、macOS/OS X 和 Windows 上运行。最新的 spaCy 版本可以通过 pipconda 获得。否则,这些命令将使您启动并运行。

pip install -U spacy
pip install -U spacy-lookups-data
python -m spacy download en_core_web_sm

使用 spaCy,我可以将文本分割成标记,并使用词性标记器来识别所有的名词、动词和形容词。我要看看每张专辑前 15 个形容词,看看会出现什么样的模式。需要注意的是,spaCy 功能强大,但并不完美。它使用统计模型来预测词性或命名实体

import spacy# load a medium-sized language model
nlp = spacy.load("en_core_web_sm")Unhallowed = album_stats['tokens'].loc[album_stats['Album'] == 'Unhallowed']a1 = nlp(str(Unhallowed[0]))

我不分析原始词,而是分析引理。词条解释是一种技术,通过将单词简化为词根形式,同时保持它是一个真实的单词,从而使语言规范化。另一种常用的规范化技术叫做词干分析。

#create a new dataframe
unhallowed = pd.DataFrame(columns=("token", "pos", "lemma"))# map with frequency count
pos_count = {}
i = 0
for token in a1:
    unhallowed.loc[i] = (token, token.pos_, token.lemma_)
    i+=1

#locate the parts of speech to keep and reset the index 
unhallowed = unhallowed.loc[unhallowed['pos'].isin(['PROPN', 'NOUN', 'VERB', 'AUX',' DET', 'ADJ', 'ADP'])].reset_index().drop(columns =('index'))

注意,在上面的代码片段中,我创建了一个 dataframe,并用单词 token、词性标记和词条填充它。当我计算 ADJ 的计数时,我将使用引理而不是令牌

unhallowed_freq = Counter(unhallowed['lemma'].loc[unhallowed['pos'] == 'ADJ'])#call the 15 most frequent
unhallowed_adjs = unhallowed_freq.most_common(15)unhallowed_adjs

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

15 个最常见的形容词

很明显,死亡、黑暗和人性的脆弱是 BDM 音乐的主题。“死亡”这个词在所有专辑中高居榜首,除了他们早期的两张热门专辑《不被允许的》和《夜间的》。虽然很多相同的词出现在每张专辑中,但还是有一些主题上的不同。例如,在夜间中,我可以看到“邪恶的”、“可怜的”和“死灵的”这些词出现了多次,它们在主题上代表了一个被抛入永恒黑暗的世界,就像这张专辑所传达的那样。使用 plotly express 条形图,数据易于可视化。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

包扎

虽然歌词只是我喜欢的死亡金属的一小部分,但分析起来很有趣。即使没有运行 K-means 或 LDA 等技术,spaCy 也可以使用标记器和命名实体识别等功能来帮助识别文本中的主题。看黑大丽花谋杀案的歌词,它们代表了愤怒和堕落,抑郁和疯狂。虽然有些人可能会因恶意的描述而回避或感到腐败,但我拥抱它和音乐,我永远是快速双踢、催眠旋律重复片段和黑色大丽花谋杀案惊人的音域的粉丝。我迫不及待地想听听他们在verminus 中会推出什么。

有关 NLP 和数据科学的更多信息,请查看我的其他教程:

[## 使用 Python 中的自然语言工具包分析葡萄酒描述

用什么词来形容酒?

towardsdatascience.com](/analyzing-wine-descriptions-using-the-natural-language-toolkit-in-python-497ac1e228d5) [## K-Means 使用 Scikit-Learn & NLTK 对 Chardonnay 评论进行聚类

霞多丽是世界上最受欢迎的白葡萄酒。聚类有助于区分高于平均水平的葡萄酒吗…

towardsdatascience.com](/k-means-clustering-chardonnay-reviews-using-scikit-learn-nltk-9df3c59527f3)

谢谢大家!

—埃里克·克莱本

使用 Python 从国家名称列表创建世界地图

原文:https://towardsdatascience.com/using-python-to-create-a-world-map-from-a-list-of-country-names-cd7480d03b10?source=collection_archive---------2-----------------------

从国家名称列表中,获取纬度和经度以创建世界地图

最近,我参与了一个项目,根据一系列简短的国家名称(如美国)创建一幅世界地图。在这里,我展示了创建世界地图(或任何其他地图)的步骤。

数据

有两列(国家名称、用户百分比)的样本数据是我们的原始数据。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1.转换为阿尔法 2 代码和大陆

alpha 2 代码更便于以后的分析,因此简短的国家名称被转换为 alpha 2 国家代码。例如,美国转换为美国。Python 的 pycountry-convert 包用于处理转换。下面的 Python 代码片段显示了一个要转换的函数。

#installation
pip install pycountry-convert#function to convert to alpah2 country codes and continentsfrom pycountry_convert import country_alpha2_to_continent_code, country_name_to_country_alpha2def get_continent(col):
    try:
        cn_a2_code =  country_name_to_country_alpha2(col)
    except:
        cn_a2_code = 'Unknown' 
    try:
        cn_continent = country_alpha2_to_continent_code(cn_a2_code)
    except:
        cn_continent = 'Unknown' 
    return (cn_a2_code, cn_continent)

在这个步骤之后,原始数据被处理如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.获取经度和纬度

第二,基于这些 alpha 2 国家代码提取经度和纬度信息。Python 的 geopy 可以使用第三方地理编码器和其他数据源轻松定位地址、城市、国家和地标的坐标。下面的 Python 代码片段展示了一个获取经度和纬度的函数。

#installation
pip install geopy#function to get longitude and latitude data from country namefrom geopy.geocoders import Nominatimgeolocator = Nominatim()
def geolocate(country):
    try:
        # Geolocate the center of the country
        loc = geolocator.geocode(country)
        # And return latitude and longitude
        return (loc.latitude, loc.longitude)
    except:
        # Return missing value
        return np.nan

在运行上面的函数并将 geolocate 拆分为两个独立的纬度和经度列后,显示了下表。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3.创建世界地图

有许多 Python 包可用于创建视觉上吸引人且信息丰富的地图,包括底图、散景和树叶等。这里,follow 用于创建某些用户分布的世界地图。Folium 的 CircleMarker()通过改变半径和颜色变量来描述数据是很有用的。

#installation
pip install folium# Create a world map to show distributions of users 
import folium
from folium.plugins import MarkerCluster#empty map
world_map= folium.Map(tiles="cartodbpositron")marker_cluster = MarkerCluster().add_to(world_map)#for each coordinate, create circlemarker of user percent
for i in range(len(df)):
        lat = df.iloc[i]['Latitude']
        long = df.iloc[i]['Longitude']
        radius=5
        popup_text = """Country : {}<br>
                    %of Users : {}<br>"""
        popup_text = popup_text.format(df.iloc[i]['Country'],
                                   df.iloc[i]['User_Percent']
                                   )
        folium.CircleMarker(location = [lat, long], radius=radius, popup= popup_text, fill =True).add_to(marker_cluster)#show the map
world_map

用户可以放大地图,查看更详细的国家用户分布情况。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这个例子中,我在几个 Python 包的帮助下创建了一个世界地图。不用说,使用给定的坐标可以很容易地创建其他类型的地理地图。

使用 Python 创建专辑中样本的 Spotify 播放列表

原文:https://towardsdatascience.com/using-python-to-create-spotify-playlists-of-the-samples-on-an-album-e3f20187ee5e?source=collection_archive---------19-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(通过去飞溅

用循环和随机样本交换鼓循环和灵魂样本

介绍

作为一个狂热的嘻哈迷,我一直对采样极其感兴趣。对于门外汉来说,音乐采样是将一首现有歌曲的一部分重新用作新歌的一部分的行为。一个很好的例子是坎耶·韦斯特 2005 年专辑*中的我回家的路,这是吉尔·斯科特-赫伦 1971 年专辑中的家是仇恨的地方一个人的片段 *

迟到的报名充满了从前面提到的苍鹭曲目到雪莉·贝西的经典曲目“钻石恒久远”的精彩样本,该曲目曾作为同名邦德电影的主题曲。听了无数遍《迟到的登记》( Late Registration )( T23 ),我想更深入地了解音乐,并探索韦斯特和联合制作人乔恩·布里昂(Jon Brion)通过采样对文字的影响。我开始在 Genius 上搜索歌曲,找到样本的名称,并手动将它们添加到 Spotify 播放列表中。不出所料,过了一段时间后,这变得很麻烦,所以我写了一个脚本来自动化这个过程。下面,我将以后期注册为例演示脚本是如何工作的,但是如果你想直接跳到代码中,你可以在我的 GitHub 上找到。**

网页抓取

第一步是生成来自延迟注册的样本列表。如前所述, Genius 拥有大量关于每首歌曲样本的众包数据,因此只需收集专辑中每首歌曲页面的链接,循环浏览它们,并从每首歌曲中收集样本信息:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Genius 关于“我回家的路”的曲目信息

使用 Python 模块 BeautifulSoup4 和请求

至少我是这么认为的。在使用这种策略运行 scraper 时,看到结果数据帧包含 12 个结果(其中两个是重复的),我怀疑 scraper 丢失了信息,所以我在 Genius song 页面上做了一些手动检查以找出原因。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

天才歌曲页为《晚期》作者坎耶·韦斯特

事实证明,一些 Genius 歌曲页面上的样本信息位于介绍性制作注释中,而不是歌曲的信息框中。这是一个令人沮丧的认识,但它促使我设计一个解决方法。

从注释中获取样本数据

像 Spotify 一样,Genius 也有一个免费 API ,它允许用户提取关于特定注释的信息,所以一旦我分离出注释,我只需要提取样本信息。因为注释不是标准化的,所以解析文本以确定样本的名称并不简单。然而,我注意到,每当 Genius 用户引用样本时,他们都会提供一个附带的 Youtube 链接。多么体贴。利用这些信息,我能够开发一个补充的 scraper,该 scraper 隔离一个 Genius 产品注释,并通过在注释中抓取 Youtube 视频的标题来输出示例信息:

现在配备了这个更健壮的 scraper,我们可以看看从晚注册Genius URL 输出的数据:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

信息框中的示例数据(作者截图)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来自注释的示例数据(作者截图)

接下来,我将这两个数据帧分别称为sample_datatitles。尽管由于数据帧中存在重复的轨道,刮刀可能会出现一些错误,但这实际上是刮刀正在工作的证据。后期注册的前两首曲目,“ 叫醒韦斯特先生”和“听见他们说”被这首华丽的娜塔莉·科尔曲目的样本出色地联系在一起,前者原样采样介绍性的钢琴部分,后者采用循环上的一段相同的钢琴部分作为其节拍的基础《钻石是永恒的》出现了两次,因为这张专辑包含了原版的"来自塞拉利昂的钻石",它是 Bassey 曲目的样本,也是这张专辑的主打单曲,还有一张由 Kanye 的导师 Jay-Z 演唱的混音版

使用 Spotify 创建 Spotify 播放列表

下一步是自动创建一个恰当命名的 Spotify 播放列表,这可以通过Spotipy模块轻松完成。启动Spotipy是一个的简短过程,它可以归结为向 Spotify 注册为开发人员,以获得一个客户端 id 和一个客户端密码,结合一个活跃的 Spotify 用户名,允许你通过 Spotify 的免费 API,通过 Python 对你的 Spotify 帐户执行无数操作。我使用 Spotipy 的“授权代码流”来授权使用我的帐户,然后创建一个 Spotipy 对象:

**token = util.prompt_for_user_token(username,scope,client_id=client_id,client_secret=client_secret,redirect_uri='http://localhost/') 
sp = spotipy.Spotify(auth=token)**

现在我们可以创建播放列表了:

**playlist_name = f"Samples in {album_title} by {album_artist}"    sp.user_playlist_create(username, name=playlist_name)**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Spotify 上的播放列表

非常简单。执行这段代码后,我们在 Spotify 上有了一个标题描述性的播放列表,可以添加歌曲了。

向播放列表添加曲目

不幸的是,将曲目添加到播放列表并不像提交您想要的曲目列表那么简单,但我们不做数据科学,因为这很容易。我们这样做是因为这很难,因为创建 Spotify 音乐播放列表的挑战将有助于组织和衡量我们最好的精力和技能,因为这是一个我们将接受的挑战,一个我们不愿意推迟的挑战,一个我们打算赢得的挑战!但是,我跑题了。

下面是我写的一些代码,用于从sample_data数据帧和 Youtube 视频标题列表中获取 Spotify 曲目 id 列表。我使用了Spotipyfuzzywuzzy,这是一个模糊字符串匹配模块,我稍后将讨论它的用途:

由于我采取了一些不直观的步骤,我们将更详细地分解这段代码。我通过实验发现,Spotify 搜索的第一个结果并不总是想要的曲目,这是由于 Spotify 搜索算法的特性,我不会假装理解,因此有必要检索多个结果:

**results = sp.search(q=f"{sample_data['title'][i]} {sample_data['artist'][i]} ", limit=5, type='track')**

然后,我必须验证五个回答中的哪一个是我首先想要的音轨。诚然,我第一次尝试这样做是一个彻底的失败。我当时年轻乐观,认为 Spotify 搜索结果的标题会与众包网站 Genius 从网上搜集的标题完全一致。他们没有。作为一名经验丰富的老手,我通过模糊(近似)字符串将 Spotify 结果的艺术家和曲目标题与sample_data数据帧中列出的艺术家和曲目标题进行匹配。下面是代码的简化版本:

**if fuzz.partial_ratio(Spotify_artist_name, sample_data_artist_name) > 90 and fuzz.partial_ratio(Spotify_track_title, sample_data_track_title) > 90:                    
track_ids.append(Spotify_track_id) #append track id** 

由于几乎不可能从 Youtube 视频的标题中区分艺术家和曲目名称,因此我们无法核实 Spotify 在注释工作流程中的结果。然而,这一工作流程产生了许多我们在其他情况下不会发现的额外样品,因此我发现其好处超过了潜在的成本。

关于模糊字符串匹配的简短说明

模糊字符串匹配包含一组量化两个字符串相似程度的方法。他们这样做的方法是计算使一个字符串与另一个字符串完全匹配所需的改变次数(想想替换一个字母,删除一个空格)。我将用一个例子来说明为什么我们需要这种技术:

如果你检查上面的sample_data数据框,你会看到“凯吉夫妇”的“天梦”在 Spotify 上,这支乐队的名字是“凯吉斯”艰难。显然,如果我们对艺术家姓名进行精确匹配,我们不会在播放列表中找到这个正确的样本。但是,通过使用fuzzywuzzy函数partial_ratio(),它是一个模糊字符串匹配算法的实现,我们得到:

**fuzz.partial_ratio("The Kay-Gees", "The Kay Gees")
100**

由于一些差异比这更具戏剧性,我将艺术家和曲目标题字符串的匹配阈值都设置为 90,但请随意试验您自己的!

将曲目添加到播放列表

幸运的是,将曲目添加到播放列表就像提交您想要的曲目的曲目 id 列表一样简单,这正是上面的GetTrackIDs()函数的输出。我们需要的唯一附加信息是我们之前创建的播放列表的playlist_id:****

现在我们将曲目添加到播放列表中:

**sp.user_playlist_add_tracks(username, playlist_id, track_ids)**

*瞧啊。我们在 Kanye West 的*晚注册上有一个相当广泛的歌曲样本播放列表。唯一明显的错误是管弦乐版的《钻石恒久远》(Diamonds is Forever),在我看来,这是一个小小的代价,以确保我们包括纽约社区合唱团 1977 年的《自从你走进我的生活》,它为西部经典的旋律提供了核心的号角,“快克音乐

我希望你阅读这个演示的乐趣有我制作它的一半多,因为我玩得很开心。我的 GitHub 上有更多与音乐相关的项目。

使用 PyRFC 使用 Python 将数据插入 SAP

原文:https://towardsdatascience.com/using-python-to-insert-data-into-sap-with-pyrfc-5eb2ceeda79b?source=collection_archive---------9-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

约翰·汤纳在 Unsplash 上拍摄的照片

如何用使用最多的语言将一个机器学习方法的结果插入到 SAP 中开发机器学习模型?

今天,我们看到机器学习(ML)开发的日益增长,最大的开发工具是 Python,每天都有越来越多的人试图将 ML 模型的结果返回到他们的企业资源规划系统(ERPs)中。

SAP 是最常用的 ERP 系统之一,要将 ML 模型的结果插入其中,我们有两种选择,一种是在自定义 SAP 事务中手动插入,另一种是使用远程函数调用(RFC ),这是 SAP 系统和其他系统之间通信的标准 SAP 接口,因此 RFC 调用要在远程系统中执行的函数。

假设您可以使用机器人流程自动化系统(RPA)自动上传事务中的结果文件,那么我们应该选择哪一个呢?

嗯,如果我必须选择其中一个,我会选择第二个选项,因为它往往比第一个变化更小,更新更少,所以你可能会有更少的问题与未被注意的更新。

需要指出的重要一点是,RFC 有许多目标和方法有待开发,我们想要使用的是将数据插入表格

我们可以使用 PyRFC 包用 Python 来实现,但是它的第一次使用并不那么简单,所以为了帮助我们,我创建了一些函数和文档。

我们开始吧!

装置

-第一步:下载 SAP NW RFC SDK

SAP NW RFC SDK 是 SAP NetWeaver 远程函数调用系统开发工具包的缩写,它允许您管理 RFC。

我从 Informatica of 找到了一本非常好的如何下载它的手册,但它是针对旧版本的,现在一些图标已经完全不同了,所以我写下了步骤并重印了图片以更新它。

如果想看 Informatica 的手册,文末有链接作为出处。

下载这些内容的一个困难是你需要一个 SAP 账户,所以在开始这个旅程之前,试着去申请一个。

回来,下载步骤:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作家

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作家

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作家

  • 单击下载软件图标。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作家

观察,一旦您登录,用户图标的颜色会变成蓝色

  • 单击支持包和修补程序选项卡。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作家

  • 从列表中单击“按类别”。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作家

  • 从列表中单击其他组件。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作家

  • 从列表中单击 SAP NW RFC SDK。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作家

  • 单击 SAP NW RFC SDK 的最新版本。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作家

  • 选择要下载的操作系统

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作家

  • 单击超链接。zip 文件来下载库。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作家

  • 提取中的文件和文件夹。压缩到您的 SAP 文件夹

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作家

突出显示的文件夹和文件是. zip 文件中的内容。

一旦你做到了这一点,一切都从 SAP 端设置好了。

-第二步:安装软件包

这比上一步简单一点,只需在 Python 终端上分别编写和运行这两行代码。

pip install pyrfcpip install pynwrfc

我想你可能只需要运行第二个,但是我已经安装了它们,我更愿意告诉你也安装它们,而不是你不能使用 PyRFC 包。

编码

酷,现在你已经到了有趣的部分!

Obs:如果您必须打开虚拟专用网络(VPN)才能访问 SAP,那么在使用这些功能时您也需要打开它。

对于这个开发,我们将有两个文件:常量。和 sap_rfc_connection .py

里面的常数。我们存储三样东西,带有 SAP 登录凭证的字典,RFC 函数和表名,以及每次 RFC 调用要插入的行数。

现在,在 sap_rfc_connection 中。py 我们有两个主要功能:

  • desc 功能区
def rfc_func_desc(dict_sap_con, func_name):
    '''consult the RFC description and needed input fields

    Parameters
    ----------
    dict_sap_con : dict
        key to create connection with SAP, must contain: user, passwd, ashost, sysnr, client
    func_name : str
        name of the function that you want to verify

    Returns
    -------
    funct_desc : pyrfc.pyrfc.FunctionDescription
        RFC functional description object
    '''
    print(f'{time.ctime()}, Start getting function description from RFC')
    print(f'{time.ctime()}, Start SAP connection')
    # create connection with SAP based on data inside the dict
    with Connection(**dict_sap_con) as conn:
        print(f'{time.ctime()}, SAP connection stablished')
        # get data from the desired RFC function
        funct_desc = conn.get_function_description(func_name)
        # display the information about the RFC to user
        display(funct_desc.parameters[0],funct_desc.parameters[0]['type_description'].fields)
        # return it as a variable
        return funct_desc
    # how the whole command is inside the 'with' when it ends the connection with SAP is closed
    print(f'{time.ctime()}, SAP connection closed')
    print(f'{time.ctime()}, End getting function description from RFC')

现在是它如何工作的一个例子,这个函数的主要目标是让你得到完整的 RFC 描述,并把它存储到一个变量中,这样你以后可以参考它(你也可以查看 PyDrive 文档,看看你可以用它做的所有事情),并向你显示使用 RFC 需要什么,比如字段名和数据类型。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作家

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作家

这很有用,因为有了它们,我们就知道了数据框的结构/列名以及每个字段中必须使用的数据类型,以免出错。

在我的例子中,我创建了下面这个数据框来测试。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作家

数据框创建后,我们可以继续第二个功能。

  • df_to_sap_rfc
def df_to_sap_rfc(df, dict_sap_con, func_name, rfc_table):
    '''ingest data that is in a data frame in SAP using a defined RFC, checking if the dataframe has the same size, column names and data types

    Parameters
    ----------
    df : pandas.DataFrame
        dataframe that is going to be used to insert data to SAP
    dict_sap_con : dict
        dictionary with SAP logon credentials (user, passwd, ashost, sysnr, client)
    func_name : string
        name of the RFC function
    rfc_table : string
        name of the rfc table you are going to populate

    Returns
    -------
    None
    '''
    # get needed parameters from RFC
    lst_param = get_rfc_parameters(dict_sap_con, func_name)
    # check dataframe input
    check_input_format(df, lst_param)
    # insert data
    lst_res = insert_df_in_sap_rfc(
        df, dict_sap_con, func_name, rfc_table)

这个函数包含了另外三个方法,但是为了不在它们上面浪费太多时间,前两个方法是检查数据帧是否符合 RFC 请求的格式(列名和数据类型),如果不符合,它就停止执行,以免将错误的数据插入 SAP。

真正的“神奇”发生在第三个函数中,insert_df_in_sap_rfc 函数:

def insert_df_in_sap_rfc(df, dict_sap_con, func_name, rfc_table):
    '''Ingest data that is in a data frame in SAP using a defined RFC

    Parameters
    ----------
    df : pandas.DataFrame
        dataframe that is going to be used to insert data to SAP
    dict_sap_con : dict
        dictionary with SAP logon credentials (user, passwd, ashost, sysnr, client)
    func_name : string
        name of the function that you want to remotelly call
    rfc_table : string
        name of the table which your RFC populates

    Returns
    -------
    lst_res : list
        list of dictionaries with field names and data types used in RFC
    '''
    print(f'{time.ctime()}, Start data ingestion to SAP process')
    # create an empty list that is going to recive the result
    lst_res = []
    # get the quantity of rows of the dataframe
    rows_qty = len(df)
    # define the number of execution, getting the entire part of the division and 
    # adding 1 to it, to execute the last rows that don't achieve the quantity of 
    # an extra execution
    iter_qty = (rows_qty // c.rows_per_exec) + 1
    print(f'{time.ctime()}, Start SAP connection')
    # create connection with SAP based on data inside the dict
    with Connection(**dict_sap_con) as conn:
        print(f'{time.ctime()}, SAP connection stablished')
        # for each iteration
        for i in range(iter_qty):
            # define the first and last row for this execution
            f_r = i*c.rows_per_exec
            l_r = min((i+1)*c.rows_per_exec, rows_qty)
            # define an auxiliar dataframe with only the rows of this iteration
            df_aux = df.iloc[f_r:l_r]
            print(f'{time.ctime()}, Rows defined')
            # convert this dataframe to a json format, oriented by records
            # this is the needed format to do a multirow input with a RFC
            # by last all the json data must be inside of a list
            lst_dicts_rows = eval(df_aux.to_json(orient='records'))
            # once we have the desired rows well formatted we must tell for
            # which table we are going to insert it
            dict_insert = {rfc_table: lst_dicts_rows}
            print(f'{time.ctime()}, RFC input format applied')
            print(f'{time.ctime()}, Start sending rows {f_r} to {l_r-1}')
            # with everything set just call the RFC by its name 
            # and pass the connection dict
            try:
                result = conn.call(func_name, **dict_insert)
                exec_ind = True
            except:
                result = None
                exec_ind = False
            print(f'{time.ctime()}, Rows {f_r} to {l_r-1} sent')
            # save the row's numbers, execution indicator and the result of the call in the list
            # as a dict
            lst_res.append({'row':f'{f_r}_{l_r-1}', 'exec_ind':exec_ind, 'rfc_result':result})
    # how the whole command is inside the 'with' when it ends the connection with SAP is closed
    print(f'{time.ctime()}, SAP connection closed')
    print(f'{time.ctime()}, End data ingestion to SAP process')
    return lst_res

长话短说,这段代码获取 constants.py 中定义的每次执行的行数,并计算将数据框完全插入 SAP 的迭代次数。

之后,它会将您的数据框分割成多个片段,将它们转换成一个面向记录格式的. json 文件,并将其全部放入一个列表中,最后,它会存储在一个字典中,该字典的关键字是 RFC 表名。

这种来来去去可能有点混乱,但是它创建了一个字典,允许我们一次向 SAP 表中插入多行。

最后,如果一切都设置好了,您将得到如下结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作家

如果你对这些文件感兴趣,你可以通过下面的链接在我的 Git Hub 中看到它们:

[## rfpcordeiro/python-sap-RFC-connection

使用远程函数调用(RFC)更容易地使用 PyRFC 将数据插入 SAP 的函数 GitHub 是 over…

github.com](https://github.com/rfpcordeiro/python-sap-rfc-connection)

如果您正在考虑在一个必须定期重复的过程中使用 PyRFC,也许下面的这篇文章可以帮助您安排它。

[## 自动化并安排 Python 代码的执行

让您的代码按照您的计划工作

medium.com](https://medium.com/better-programming/automate-and-schedule-your-python-code-executions-22c3ed27794e)

这就是了!

嗯,有了这个,我想你现在可以使用 Python 和 RFC 更轻松地将数据插入 SAP 了!

希望这篇文章对你有帮助!

特别感谢莱昂纳多·拉莫斯和安德森·泰西托利,当我和他们一起解决了一百万个 RFC 问题的时候,他们忍受了我

来源:

https://kb . informatica . com/h2l/how to % 20 library/1/0953-howtodownloadandstallsapnetweaverrfcsdklibraries-h2l . pdf

https://python . hotexamples . com/examples/pyrfc/Connection/call/python-Connection-call-method-examples . html

https://sap.github.io/PyRFC/client.html#examples

https://sap . github . io/py RFC/install . html # sap-NW-RFC-SDK-installation

使用 Python 将股票数据可视化为蜡烛图

原文:https://towardsdatascience.com/using-python-to-visualize-stock-data-to-candlestick-charts-e1a5b08c8e9c?source=collection_archive---------5-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

M. B. M.Unsplash 上拍摄的照片

烛台数据是一个非常重要的方式来显示数据在股票市场如何移动。有些人可能用它来观察股票价格。有些人可能还会添加颜色,以便更好地形象化。许多人还用它来绘制交易模式。它们也非常有用,因为它们不是显示一个股票价格,而是有四个不同的价格点。这些包括开盘价、收盘价、最高价和最低价。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由https://www.newtraderu.com/提供

概述代码

假设你以前有 Python 知识,我将在一个 Jupyter 笔记本中创建这一切。我将使用[pandas_datareader](http://pandas_datareader)从雅虎获取数据。然后,我将使用[plotly](https://plotly.com/)来绘制这些信息,将它们可视化到烛台上。所以一个简单的大纲应该是这样的:

  1. 导入必要的库
  2. 使用pandas_datareader从雅虎获取数据
  3. 将数据存储到数据帧中
  4. 将数据框与plotly烛台格式匹配
  5. 使用plotly将数据框中的数据可视化

创建代码

从 Jupyter 开始,我做所有必要的进口。

对于这个例子,我将使用微软作为我的股票。我将股票代码设置为一个变量,然后使用pandas_datareader从 Yahoo 获取信息并存储到一个变量中。它应该自动保存为 DataFrame 对象。对于日期,我只是把它设置为去年年初。

为了让plotly理解我们的数据,我们需要将它与正确的信息相匹配。他们把它变得简单,使用“痕迹”,把痕迹看作图形的选项。我们从数据帧中定义我们想要使用的内容,然后在选项中设置这些内容。

我们现在可以在plotly中设置图表布局。

然后我们现在可以展示可视化。它应该看起来像这样。请随意使用工具来改变它。

奖金

均线也可以作图!大多数交易者使用均线来观察股票的走向。有些人还使用不同的日期,在这些天里,如果 T2 交叉(当不同的移动平均线交叉时)发生,他们可以用它作为买入或卖出的信号。将它添加到我们的代码中非常简单。我们只是为每条均线创建单独的轨迹。我创建了一个 30 天均线的轨迹和一个 50 天均线的轨迹。

更新后的图表应该如下所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这是使用 Python 将股票绘制成烛台的简单方法。使用跟踪可以添加更多的数据。我希望这对刚开始学习 Python 并且对金融数据感兴趣的人有所帮助。此外,这还深入研究了数据可视化,这使得模式的识别更容易。

我其他一些涉及 Python 和 Robinhood 的文章:

[## 使用 Python 和 Robinhood 创建一个简单的低买高卖交易机器人

所以我最近一直在折腾 Robinhood,一直在努力理解股票。我不是财务顾问或…

towardsdatascience.com](/using-python-and-robinhood-to-create-a-simple-buy-low-sell-high-trading-bot-13f94fe93960) [## 使用 Python 和 Robinhood 构建一个钢铁秃鹰期权交易机器人

所以我最近发现了期权交易的潜在收益。

towardsdatascience.com](/using-python-and-robinhood-to-build-an-iron-condor-options-trading-bot-4a16e29649b0)

以上代码可以在这里找到,请随时关注我的交易之旅这里

我在这里也有家教和职业指导!

如果你们有任何问题、评论或顾虑,请不要忘记通过 LinkedIn与我联系!

在 Numpy 中使用 Q-Learning 玩游戏

原文:https://towardsdatascience.com/using-q-learning-in-numpy-to-teach-an-agent-to-play-a-game-4fee32eb922a?source=collection_archive---------35-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

有一些机器学习模型可以被训练以基于训练期间使用的输入-输出对将任何给定的输入映射到期望的输出。通过输入输出对,我显然是指输入和它各自的基础事实或标签。这种算法被称为监督学习算法。分类和回归就是其中的一些例子。

此外,存在一类机器学习模型,它们在数据中寻找潜在的模式,而不需要明确地知道标签。这些算法被称为无监督学习算法。聚类和密度估计就是其中的一些例子。

除了监督学习和非监督学习,还有第三种机器学习范式,称为强化学习,它与前两种类型有着根本的不同。

这基本上包括在一个环境中做出连续的决策,以最大化累积的未来回报。稍后我会更详细地解释这一点。

Q - 学习就是这样一种无模型强化学习算法,它学习在各种情况下做出正确的动作。

让我们首先熟悉强化学习设置的基本术语。

让我们熟悉一些基本的 RL 术语

有一种叫做环境的东西,它实际上包含了构成系统的所有东西。它有一个代理,它观察环境(从环境中获取输入),然后根据输入采取动作,改变环境的状态,并在此过程中收集奖励

如果这对你来说还不够完美,请不要担心!

让我们借助一个例子来理解这一点。

于是就有了 6x 6 的网格。我们让代理在网格中 6x6=36 个可能的单元中随机产生。同样,在我们网格世界的另外两个细胞中,我们有一瓶啤酒和一种致命的病毒。药剂、一瓶啤酒和致命病毒每次都会在独特的细胞位置上繁殖。代理人想要够到啤酒瓶子,以避免可能感染它的病毒,并因此结束游戏。对代理移动的限制是它只能在任何对角线方向上移动一个单元格。

在这个设置中,我们的 6x6 网格世界就是环境。代理可以访问它相对于一瓶啤酒(奖励)和致命病毒(敌人)的位置,我们称这个代理可以访问的环境信息为状态。根据环境的当前状态,代理可以采取某些预定义的动作,比如在四个对角线方向的任何一个方向上移动一个单元。代理的行为可能会给它一瓶啤酒(一个正奖励)或者它可能会让代理被致命病毒感染(一个负奖励)。因此,代理人的目标是通过与环境互动来了解它的环境,并最终学会采取行动,以使未来的累计回报最大化。

状态、动作和奖励的顺序,直到它全部结束(要么伸手拿啤酒瓶,要么被病毒感染),被称为

导致情节终止的状态称为终端状态。在我们的网格世界的例子中,代理人相对于啤酒瓶或病毒的相对位置变为零的状态是终端状态。

回报是未来奖励的累计总和。在没有终端状态的情况下,这可能达到无穷大,也称为非情节任务。为了使它成为一个有限的总和,我们使用一个叫做 gamma 的贴现因子来贴现未来的奖励。

下面是 t 时刻的回报公式,用不同时间点的回报来表示。这里 T 是最终的时间步长,γ是贴现率,使得 0≤γ≤1

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

价值函数是状态(或状态-动作对)的函数,估计代理处于给定状态有多好(或在给定状态执行给定动作有多好)

价值函数总是相对于称为策略的特定行为方式来定义的。

一个政策只不过是从状态到选择每个可能行动的概率的映射。

我想多谈谈状态-行动价值函数,因为我们将在博客的其余部分使用它。

如前所述,状态-动作函数是一个返回预期收益的函数,从状态“s”开始,采取动作“a”,然后遵循策略 π

因此,比较给定状态的状态-动作函数值和动作空间中的所有动作,可以引导我们找到在该状态下可以采取的最佳可能动作。这实际上是我们的代理如何选择在给定状态下可以采取的最佳行动。

Q 表是由所有状态-动作对组成的表。这就像一个查找表,如果给出一个当前的状态和动作,我们可以得到状态-动作或 q 值。

我们最初用随机数初始化 q 表,然后随着代理在各种状态下继续采取各种行动,继续更新每个状态-行动对的值。在代理对环境进行了一定程度的探索之后,我们可以通过使用 q 表来判断对于任何给定的状态应该采取哪种最佳行动!

是不是很疯狂!😄

让我们把手弄脏吧!

我们现在要学习如何实现 q-learning。这将是一次有趣的旅程。😄,系好你的安全带

我们从导入所有必需的库开始。

然后,我们定义了 q 学习算法和显示窗口的所有超参数。

接下来,我们为我们的代理、啤酒瓶(正奖励)和病毒(负奖励)定义图像的路径,并读取它们以显示在屏幕上。这只是为了让显示窗口看起来有趣。

我们需要创建一个名为**【Blob】的类,我们的代理、啤酒瓶和病毒将继承这个类。一个 Blob 类对象将有一个相关联的生成位置(x 和 y 坐标),它将能够根据其‘移动’**方法中传递的输入进行对角移动。我们也能够加减两个斑点对象。它将简单地增加或减少两个斑点对象的 x 和 y 坐标。

现在让我们来定义 q 表,它将被一次又一次地用来选择给定状态下的最佳行动。我们将不断更新此表,以提高我们代理商的决策能力。

请注意,这里我们对状态空间的取值范围是 -SIZE+1 到 SIZE 。这是因为我们将状态空间定义为啤酒瓶和病毒之间的相对位置。所以这可以是正面的,也可以是负面的。例如,如果网格世界的大小是 6,那么代理相对于啤酒瓶的相对位置将从-5 变化到 5。

现在不要担心更新 q 表中 q 值的更新规则。我们稍后会谈到这一点。

在每一集里,我们的特工、啤酒瓶和病毒都需要在特定网格世界的特定细胞位置繁殖。但是我们的 Blob 类只是在 grid-world 中的一个随机单元位置上产生了一些人。这可能会导致角色在同一位置产生,这是我们不希望的。为此,我们编写了一个函数,它将一个元组列表作为输入,该列表包含已经被繁殖的个体的坐标。这将确保任何两个家伙,代理人,啤酒瓶和病毒不共享他们的细胞位置。

设置和定义好一切后,我们开始训练代理(更新 q 表)。

这就是奇迹发生的地方。

让我们一行一行来理解。所以我们从一个循环开始,这个循环将运行规定的集数。

我们使用前面已经定义的get _ unique _ spacing _ location函数和 Blob 类来初始化播放器、啤酒和病毒对象。

然后,我们使用 SHOW_EVERY 参数来打印 epsilon 的当前值、到目前为止的平均奖励(这应该随着训练而增加)以及用于显示实际网格世界的显示参数**‘SHOW’**。

接下来,我们将**‘插曲 _ 奖励’**初始化为 0,代理开始采取 200 个时间步长的动作。

对于每个时间步长,我们需要环境的状态,我们将它定义为代理相对于啤酒瓶和病毒的相对位置。

那么代理将需要采取行动,这也将取决于ε的当前值。我们从均匀分布中抽取一个随机数,并将其与 epsilion 的当前值进行比较。如果随机值大于ε的当前值,则代理使用 q 表并选择 q 表中具有最大 q 值的动作。否则代理采取随机行动。

代理利用 q 表挑选具有最高 q 值的动作的第一种情况被称为利用,而代理采取随机动作的第二种情况被称为探索。参数ε负责开发-勘探权衡

然后,我们检查代理是否接触到啤酒瓶,或者它是否被病毒感染。我们相应地定义当前时间步长的奖励。

然后代理采取行动,导致它在网格世界中的状态发生变化。

然后,我们计算新的 q 值,并使用下面提到的公式更新 q 表。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了显示网格世界和这些家伙,我们制作了一个空画布,根据 DISPLAY_SIZE 参数调整大小,并将代理、啤酒瓶和病毒的图像粘贴到它们各自的当前位置。

最后,如果代理人得到了他的啤酒或者他被病毒感染了,我们就打破了这个循环。

我们计算移动平均线,并绘制回报图。

最后,我们保存更新的 q 表。

结果

下面是报酬移动平均值的曲线。它的上升趋势表明,随着越来越多的训练,代理变得越来越聪明。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

移动平均数

这里有一些 gif 展示了代理如何在每一次训练中变得更聪明。

这是一个口渴的代理用随机初始化的 q 表寻找一瓶啤酒。这意味着代理还没有关于环境的线索。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

愚蠢的代理人想要啤酒,但没有得到它

经过一些训练后,代理人在做出连续决策方面做得相对更好。他还不是很快,但他最终找到了啤酒。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

嗯,这样更好

最后,经过数千次的训练,代理人真的很擅长做连续的决定,并且很快就找到了啤酒!😄

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这才是个聪明的特工!b)

Q 学习的优势

这是一个易于理解和实施的简单概念。它非常适合没有巨大国家行为空间的环境。

Q 学习的局限性

q 学习包括从 q 表中查找。并且 q 表由每个可能的单个状态-动作对的值组成。因此,随着状态空间的增加,q 表的大小呈指数增长。因此,Q-Learning 有利于在状态-动作空间较小的环境中训练智能体。对于更复杂的设置,使用深度 Q 学习。

密码

你可以在我的 GitHub 账号上找到这个 q-learning 项目的代码,点击这个链接【https://github.com/n0obcoder/Q-Learning】

参考

  1. 【https://www.youtube.com/playlist? list = plqvvvaa 0 qudezjfiou 5 wddfy 4 e 9 vdnx-7
  2. https://www . coursera . org/learn/fundamentals-of-reinforcement-learning
  3. https://web . Stanford . edu/class/psych 209/Readings/suttonbartoiprlbook 2 nded . pdf

我写这篇博客是因为我通过阅读别人的博客学到了很多东西,我觉得我也应该尽可能多地写下并分享我的学习和知识。所以,请在下面的评论区留下你的反馈,让我知道如何改进我未来的博客!😄

我也是一个独立的音乐艺术家,喜欢在空闲时间演奏和录制音乐。也许你可以看看我的艺人页面,表示支持:)
Spotify 上的 8 楼和声!

在 Google Sheets 公式中使用 R 和 Python

原文:https://towardsdatascience.com/using-r-and-python-in-google-sheets-formulas-b397b302098?source=collection_archive---------9-----------------------

Google Sheets 中的自定义编程语言功能

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Unsplash 上由 Carlos Muza 拍摄的照片

谷歌床单太神奇了!

谷歌的电子表格版本叫做谷歌表格,它有一个隐藏的宝石,可以显著增加你的电子表格的功能,叫做谷歌应用程序脚本。Google Apps Script 使用 Javascript 调用其他 Google 服务,创建交互式弹出对话框,甚至进行 API 调用。通过一点设置,您可以创建电子表格公式供其他人使用,执行 R、Python 或几乎任何编程语言代码!虽然 Shiny 和 Dash 是分享您的工作的好方法,但是按照本文中的说明,您将能够直接在 Google Sheets 中创建 R 和 Python 仪表板。另外,这些方法允许您将 R 和 Python 功能插入到其他 Google 服务中,比如文档、表单和幻灯片!

这里有几个例子

  1. 矩阵乘法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

2。绘图(基数 R)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

3。绘图(ggplot2)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

4。部署模型

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

5。任何 R 脚本!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

这是什么魔法**?**

在幕后,每个自定义函数都是一个 Google Apps 脚本,它对我在 Google Cloud Run 中设置的一个端点进行 API 调用。如果您可以设置运行 R、Python 或任何其他语言脚本的 API 端点,那么您可以将这些功能导入到 Google 电子表格中。这是惊人的!

尝试一下

下面的 6 个步骤从最容易到最难排列,将简单地让你开始使用你自己的定制的电子表格函数。关于 Google Apps 脚本、创建自己的 API 和 Google Cloud Run 还有很多内容可以在另一篇文章中介绍。

  1. 在 Google Drive 中创建电子表格
  2. 工具菜单- >脚本编辑器

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

3.将下面的代码复制并粘贴到编辑器中。适应你的需求。

/**
 * Run an R, Python, or other language script on spreadsheet data.
 *
 * [@param](http://twitter.com/param) var1 The value or cell contents to pass to your API.
 * [@param](http://twitter.com/param) var2 The value or cell contents to pass to your API.
 * [@return](http://twitter.com/return) The results of the API call you're about to make.
 * [@customfunction](http://twitter.com/customfunction)
 */
function myCustomFunction(var1 = null, var2 = null){

  // Assuming your API endpoint is like {baseURL}/{endpoint}.
  var baseURL = '(Copy and paste API base url w/o trailing /)';
  var endpoint = 'myCustomFunction';

  // Encode the variable values as JSON (or XML, or something else). 
  // See Google Apps Script UrlFetchApp documentation.
  var data = {
    'var1': var1,
    'var2': var2,
  }// Set up the API call. Use POST requests to pass variables.
// You can pass variables as query params of GET requests instead.
  var options = {
    'method' : 'post',
    'contentType': 'application/json',
    'payload' : JSON.stringify(data)
  };

  // Make the API call. NOTE: Trailing slashes are important!
  var response = UrlFetchApp.fetch(baseURL + '/' + endpoint + '/', options);

  // Parse the response.
  data = JSON.parse(response.getContentText());

  // I return "Error: {the error}" on script errors. 
  // Not necessary, but it shows useful error messages in cells.
  if(String(data).substring(0,6) == "Error:"){
    throw(String(data));
  }

  return(data);
}

4.创建一个名为“Dockerfile”的不带扩展名的纯文本文件。 把它放在硬盘上自己的文件夹里。不要紧张;你不需要在你的系统上安装 Docker 来执行这些步骤(但是你绝对应该在你的日常工作中使用 Docker!)

将以下内容之一复制并粘贴到 docker 文件中。

  • R 示例 1:这里有一个 R API 的 docker 文件,它使用了令人惊奇的 Plumber 包。这不是 Tidyverse 的产品,但它能创造出苗条的形象。
FROM trestletech/plumberCOPY [".", "./"]ENTRYPOINT ["R", "-e", "pr <- plumber::plumb(commandArgs()[4]); pr$run(host='0.0.0.0', port=as.numeric(Sys.getenv('PORT')), swagger = T)"]CMD ["Plumber.R"]
  • R 示例 2:这里有一个 R API 的 rocker 文件,它确实带有 Tidyverse 和 Tensorflow(基于 rocker/ml image )。这就产生了臃肿的图像,并附带了 RStudio。它不是用来生产的。
FROM samterfa/rmlsheetsCOPY [".", "./"]ENTRYPOINT ["Rscript", "-e", "pr <- plumber::plumb(commandArgs()[9]); pr$run(host='0.0.0.0', port=as.numeric(Sys.getenv('PORT')), swagger = T)"]CMD ["Plumber.R"]
  • Python 示例:这里有一个 Dockerfile 文件,它使用了名副其实的快速 API
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7RUN pip install pandasCOPY [".", "./"]

5.创建支持自定义功能的脚本。将以下文件添加到与您的 docker 文件相同的文件夹中。请注意,Google Sheets 中的单元格引用是作为单个单元格的单个值或多个单元格的嵌套列表传入的。

  • R API 文件:创建一个名为 Plumber.R 的文件。
# Swagger docs at ...s/__swagger__/ (needs trailing slash!)
if(Sys.getenv('PORT') == '') Sys.setenv(PORT = 8000)#' [@apiTitle](http://twitter.com/apiTitle) R Google Sheets Formulas
#' [@apiDescription](http://twitter.com/apiDescription) These endpoints allow the user to create custom functions in Google spreadsheets which call R functions.#* Return the product of 2 matrices
#* [@param](http://twitter.com/param) var1 An array of values representing the first matrix.
#* [@param](http://twitter.com/param) var2 An array of values representing the second matrix.
#* [@post](http://twitter.com/post) /myCustomFunction/
function(var1, var2){

  err <- tryCatch({

    return(data.matrix(var1) %*% data.matrix(var2))

  }, error = function(e) e)

  return(paste0('Error: ', err$message))
}#* Confirmation Message
#* [@get](http://twitter.com/get) /
function(msg=""){
  "My API Deployed!"
}
  • Python API 文件:创建一个名为 Main.py 的文件。
from fastapi import FastAPI
from pydantic import BaseModelclass Matrices(BaseModel):
    var1: list
    var2: list

app = FastAPI()[@app](http://twitter.com/app).post("/myCustomFunction/")
def myCustomFunction(matrices: Matrices):

  import sys
  import numpy as np try:

    var1 = np.matrix(matrices.var1)
    var2 = np.matrix(matrices.var2)

    results = np.matmul(var1, var2)

    return np.array(results).tolist()

  except: e_type, e_value, e_traceback = sys.exc_info()

    return 'Error: ' + str(e_type) + ' ' + str(e_value)@app.get("/")
def myAPIdeployed(): return "My API Deployed!"

注意:要在 Google Sheet 中运行任意的 R 或 Python 脚本,该脚本需要确定传递的数组是否包含列名。代码有点笨拙,但是我在本文的结尾加入了一个 R 尝试。

6.部署您的 API(到 Google Cloud Run) 如果您已经知道如何部署 R 或 Python API,那么您可能已经停止阅读这篇文章并开始比赛了!对于我们其余的人,我将指导您使用 Google Cloud Run 来托管您的 API。

马克·埃德蒙森创造了一个惊人的 R 包,名为 googleCloudRunner 。这个包处理 auth,创建构建,并将容器部署到 Google Cloud Run。这真的很了不起。如果您没有安装 R,您可以遵循这些项目设置说明,以及这些部署说明,记住我们正在尝试从上面部署我们的 Dockerfile。从现在开始,我将假设您已经安装了 R running 和 googleCloudRunner。

  • 转到https://console.cloud.google.com/
  • 如果您以前从未创建过项目,请同意条款和服务。
  • 点击选择一个项目,然后新建项目
  • 命名并创建项目。我喜欢脚本、Pyscripts 或类似的东西。
  • 确保项目名称在左上方的下拉列表中。
  • 点击左侧下拉菜单,点击计费,然后添加计费账户。我保证,很便宜

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

  • 对于其余的设置,遵循马克埃德蒙森的指示这里
  • 确定包含 docker 文件和 API 文件的文件夹的路径。姑且称之为“/用户/我/我的/API/路径”。
  • 使用 R,运行以下命令来部署您的 API!在 Google Cloud Run 中创建的服务的名称将是文件夹路径中最后一个文件夹的名称,所以请确保您喜欢这个名称,并且它的名称是小写的。
googleCloudRunner::cr_deploy_run(local = "/users/me/my/api/path")# Wait, that's it? Just that?
  • 将打开一个浏览器,显示您的构建进度。如果有错误,您可以使用日志消息来确定哪里出错了。常见的问题是缺少服务帐户权限和代码问题。如果您对 Docker 感到满意,可以在本地进行测试,以确保没有代码问题。如果成功,您应该会看到一条消息(如果您复制并粘贴了我的代码)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

  • 一旦启动,你需要将上面的 API URL 复制并粘贴到你的 Google Apps 脚本中。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

  • 试试吧!在 Google 工作表中创建两个数字数组,它们可以作为矩阵相乘,开始输入“=myCustomFunction(",突出显示单元格,然后给自己留下深刻印象。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

资源

  1. 免费 APISwagger网页 这些都是自动为你生成的,因为你用了 R 包 Plumber 或者基于 Python 的 FastAPI。
  • r 版本位于{YourBaseURL}/swagger/

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

  • Python 版本位于{YourBaseURL}/docs

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

2.samterfa/rpysheets****GitHub Repo这个 Repo 包含上面列出的所有文件加上一些额外的材料。奖励材料包括通用脚本函数,以及 MNIST 数字预测函数。如果你想对大型模型进行预测,谷歌表单会给你 30 秒的时间限制。你可能还需要增强你的谷歌云运行服务。

使用 R 和 SQL 倡导哈莱姆住宅修缮

原文:https://towardsdatascience.com/using-r-and-sql-to-advocate-for-harlem-housing-repairs-8b7557644a63?source=collection_archive---------39-----------------------

为纽约市工作人员建立维修清单,以帮助哈莱姆区经济适用房的维修合规性

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

纽约市的经济适用房

经历了多年的预算短缺和不断增加的债务,纽约市住房管理局(NYCHA)在维护其五个区的 326 个公共住房开发项目的基础设施方面严重落后。

来自纽约市 40 多万租户的令人痛心的紧急维修报告每周出现在周刊上。

根据纽约市公共辩护律师办公室的数据,截至 2019 年 11 月,纽约市建筑的未完成工作订单接近 35 万份(自 2018 年以来增长了 43%)。随着这一毁灭性的消息,朱玛恩·威廉姆斯(Jumaane Williams)在 2019 年 12 月发布年度房东观察名单时,将纽约市视为“2019 年最糟糕的房东”。

作为法院创新中心的高级研究和数据助理,我的部分工作是支持哈莱姆社区司法中心(HCJC) 。21 世纪初,HCJC 作为一个解决问题的法庭而成立,为居住在哈莱姆区及其周边的个人提供支持。

我在那里承担的一个特殊项目是帮助员工跟踪住房情况。作为一个基于社区的中心,HCJC 的一部分工作是帮助倡导租户的权利,要么帮助哈莱姆区的居民向住房法院提起诉讼,要么推动纽约市跟进过时的维修——所有这些文书工作和咨询都发生在东 121 街 170 号的住房和资源中心。自该中心在 2018 年底开始跟踪这些信息以来,收到的 2000+次上门服务中,超过一半来自整个哈莱姆社区 NYCHA 大楼的租户。

如前所述,随着纽约市越来越多的维修工作订单,HCJC 决定加倍努力,利用其内部数据库向纽约市的工作人员发送维修时间表,以加快维修过程,并代表其客户进行宣传。

为此,我决定采用数据科学方法,在 SQL 和 R 中构建一个自动化流程,将我们的住房和资源中心数据从我们的内部数据库中提取到最终的 Excel 电子表格中,该电子表格列出了计划在一周的特定日期进行维修的租户的信息(请参见下面的最终产品截图)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

此工作流创建的自动化租户列表的示例。请注意,真实姓名和信息已从该截图中删除,但实际输出包括我们系统中每个租户的联系信息,计划访问日期为该周/日。

以下是工作流程的完整概述,从一名哈莱姆居民走进哈莱姆社区司法中心的大门,到发送给纽约市工作人员以跟进维修的 Excel 列表:

维修案例和自动化工作流程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们将讨论其中的自动化部分,从 SQL 步骤开始,一直到创建 Excel 文件。

SQL 查询

spool "C:\directory_name\data.csv"
SELECT /*csv*/ distinct 
.
.
.
FROM
internal tables
.
.
.
WHERE
date range variable and other parameters
spool off;

我不能共享用于该查询的特定表和变量,但是需要注意的重要一点是,我在 SQL 查询的开始声明了一个文件路径,然后指示脚本将信息放入该目录中的一个. csv 文件中。完成后,该目录将有一个假脱机列表。csv 文件本质上是从查询中创建的 SQL 视图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一旦 SQL 脚本运行完毕(不到 20 秒),我就可以打开我的 R 脚本并在这些新的。来自 SQL 的 csv 文件。

r 脚本

打开我的 R 脚本后,我会高亮显示整个脚本并点击“Run”。在运行的 15 秒钟内,它将完成以下步骤(为了节省时间,我将省略其他一些步骤):

使用的库

library(devtools)
library(statsr)
library(dplyr)
library(ggplot2)
library(tidyverse)
library(readxlsx)
library(Hmisc)
library(plyr)
library(DT)
library(XLConnect)
library(lubridate)
library(reshape)
library(xlsx)
  1. 创建一个新的 Excel 电子表格,最终保存我的最终日历/列表数据:
# GET CURRENT DATE
date <- format(Sys.Date(), "%m-%d-%Y")# EXCEL SHEET CREATED WEEKLY FOR NYCHA ACCESS/FOLLOW-UP REPAIRS
new_filename <- paste("internal_directory/nycha_accessfollowup_", date, ".xlsx", sep = "")# SAVING THE WORKBOOK IN A VARIABLE
nycha_summary <- loadWorkbook(new_filename)saveWorkbook(nycha_summary)

2.正在加载假脱机的 SQL。我之前声明的目录中的 csv 文件:

# SAVING THE SPOOLED CSV FILENAME IN A VARIABLE TO USE LATERrepair_file_name <- "repair-complaints.csv"# SET THE WORKING DIRECTORYsetwd("C:/Help Center/Zach-Housing-Resource-Center/SQL_outputs")# FILES TO LOAD repairsData <- read_csv(repair_file_name)
lengthOfData_repairs <- length(repairsData$`Episode ID`)-1
repairsData <- slice(repairsData, 1:lengthOfData_repairs)

3.一旦。csv 文件已加载,我知道根据我们从数据库收到的内部案例注释的结构,我需要创建几个函数来筛选这些条目并识别未完成的维修案例,将这些条目与其他住房案例分开,然后创建几个列来区分:

  • “无法进入”案例——被记录为 NYCHA 未能在预定日期出现在租户公寓进行维修的案例
  • “待定访问”案例—已安排但尚未实施的案例
  • “成功访问”案例 NYCHA 确实在预定日期参与了维修工作
cleanNotes <- function(dataset, dataLength){
  dataset <- dataset
  for (x in 1:dataLength){
    if(isTRUE(dataset$Note_category[x] == "Successful Access NA NA")){
      dataset$Note_category[x] = "Successful Access"
    } else if(isTRUE(dataset$Note_category[x] == "NA NA NA")){
      dataset$Note_category[x] = NA
    } else if(isTRUE(dataset$Note_category[x] == "NA NA Pending Access")){
      dataset$Note_category[x] = "Pending Access"
    } else if (isTRUE(dataset$Note_category[x] == "NA Failed Access NA")){
      dataset$Note_category[x] = "Failed Access"
    } else {
      dataset$Note_category[x] = NA
    }
  }
  return(dataset)
}

4.创建最终清洁功能,将上述功能与一些附加功能结合起来:

dataCleaning <- function(dataset, dataLength){
  dataset <- dataset
  dataset <- addAccessField(dataset)
  dataset <- checkforSuccessAccess(dataset)
  dataset <- checkforFailedAccess(dataset)
  dataset <- checkforPendingAccess(dataset)
  dataset <- dataset %>%
    mutate(Note_category = paste(Access_success, Access_failed, Access_pending))
  dataset <- cleanNotes(dataset, dataLength)
  dataset <- selectColumns(dataset)
  dataset <- parseAccess(dataset, dataLength)
  dataset <- followupDecipher(dataset, dataLength)
  dataset <- reminderDecipher(dataset, dataLength)
  dataset <- failedAccessTenant(dataset, dataLength)
  return(dataset)
}

5.隔离本周的日期:

# SEQUENCE OF MONDAYS AND FORMATTING INTO A TIBBLEmondays <- seq(as.Date("2019/01/08"), as.Date("2022/01/04"), "7 days")mondays <- format(as.POSIXct(mondays), "%m-%d-%Y")
workweek <- tibble(mondays = 1:157)# ISOLATING MONDAYS AND FRIDAYS IN THE WEEK AND DATE FORMATTINGworkweek$mondays <- mondays
workweek$fridays <- format(as.Date(mondays, format = "%m-%d-%Y") + 4, "%m-%d-%Y")# CALCULATE DAYS OF THE CURRENT WEEKcurrent_Monday <- workweek$mondays
current_Tuesday <- format(as.Date(workweek$mondays, format = "%m-%d-%Y") + 1, "%m-%d-%Y")
current_Wednesday <- format(as.Date(workweek$mondays, format = "%m-%d-%Y") + 2, "%m-%d-%Y")
current_Thursday <- format(as.Date(workweek$mondays, format = "%m-%d-%Y") + 3, "%m-%d-%Y")
current_Friday <- workweek$fridays

正如你在上面看到的,我创建了一个长列表,包含从 2019 年初到 2022 年初的每个星期一的日期。然后,从这个列表中,通过在脚本的第一部分分离出当前日期,我创建了一周的其余日子。

6.过滤维修信息以仅存储当前周的案例数据框,并将其处理成最终产品的日历/列表格式:

for(y in valuesLength){
  indexIWant <- which(!is.na(access_calendar[[y]]))
  for(j in valueOne){
    access_calendar[, columnName[y]] <- NA
    for(i in indexIWant){
      access_calendar[j,columnName[y]] <- pendingAccess_week$`Full Name`[i]
      access_calendar[j+1,columnName[y]] <- ifelse(is.na(pendingAccess_week$`Development Name`[i]), 'No Development Name Provided', pendingAccess_week$`Development Name`[i])
      access_calendar[j+2,columnName[y]] <- pendingAccess_week$`Address`[i]
      access_calendar[j+3,columnName[y]] <- ifelse(is.na(pendingAccess_week$`Home Number`[i]), 'No Home Phone # Provided', pendingAccess_week$`Home Number`[i])
      access_calendar[j+4,columnName[y]] <- ifelse(is.na(pendingAccess_week$`Mobile Number`[i]), 'No Mobile Phone # Provided', pendingAccess_week$`Mobile Number`[i])
      access_calendar[j+5,columnName[y]] <- pendingAccess_week$`Case Note`[i]
      access_calendar$index[j] <- j
      access_calendar$index[j+1] <- j
      access_calendar$index[j+2] <- j
      access_calendar$index[j+3] <- j
      access_calendar$index[j+4] <- j
      access_calendar$index[j+5] <- j
      j <- j + 6
    }
  }
}

从上面的 R 语法中可以看出,我创建了两个“for”循环来遍历一周中的日期以及在一周中有预定访问日期的租户的案例信息(每个租户总共 7 行)。

创建数据框后,我们可以在 R:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

R 数据框快照,包含访问日期的租户列表。

尽管出于保密原因,许多访问信息不得不被隐藏,但您可以看到,最终的数据框根据一周中的某一天以及 NYCHA 联系居民所需的重要租户信息,以整齐的列和行打印租户信息。

最终 Excel 输出

数据框在 R 中正确格式化后,剩下的唯一事情就是将数据框保存在我之前创建的 Excel 电子表格中,我在 R 脚本的开头表示:

# SAVE THE DATA FRAME IN AN EXCEL SPREADSHEETwb <- openxlsx::write.xlsx(access_calendar, file = new_filename, col.names = TRUE)

我之前也分享过的最终产品如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

自动化流程的最终 Excel 输出。

从运行 SQL 查询到获得 Excel 输出的整个过程每周花费大约 1 分钟

这一进程的初步效果

对于这样一个每周一次的任务,利用 R 和 SQL 来自动化这个过程是必不可少的。

很难将维修合规率的提高直接归因于我们对该流程的实施,但是,早期的分析表明,我们对这类工具的跟进和尽职调查为与住房和资源中心互动的哈莱姆居民带来了更好的结果。至少,我们能够向 NYCHA 工作人员和利益相关者提供的更多信息只会有助于他们跟进居民的维修投诉。

当我们寻求在这些问题上与城市机构更紧密地合作,并最终帮助整个哈莱姆社区的居民时,自动化工具将在沟通各方和协助赤字方面发挥越来越重要的作用,例如及时解决经济适用房维修案件。

第一次使用 R?

原文:https://towardsdatascience.com/using-r-for-the-very-first-time-7d78c526ae68?source=collection_archive---------43-----------------------

最近,我的任务是让一名实习生熟悉 R。当我考虑如何最好地指导他时,我想起了当 R 对我来说完全陌生时,我是多么努力地站稳脚跟。我最初发现了这么多解释各种包、最佳实践和分析的伟大资源,但是我甚至不知道在哪里键入我的代码!我最终通过 YouTube 视频拼凑出了对 R 用法的大致理解,感觉自己正在成功前进。

然后,我很幸运地在研究生院学习了一个非常棒的基于 R 的数据科学资源,并意识到我的代码一团糟。我不知道 R 项目和 R Markdown 文件的存在,所以我所有的代码都存在于桌面上组织混乱的脚本中。我通过给自己发电子邮件来备份我的工作,并利用了现在让我畏缩的变量名和间距。那门课程帮助我学会了如何创建不仅可以运行,而且可重复的代码,这有助于我的数据分析团队进行有效的协作。

希望帮助这位实习生避免我最初的错误,我编写了以下 r 入门指南。它是为完全的初学者设计的——第一部分实际上涵盖了安装软件的位置!我确保包含了我在数据科学课程中学到的许多重要经验,因此在创建本指南时经常参考课程网站。我分享这个链接不仅是为了赞扬杰夫·戈德史密斯的想法,也是为了给那些寻找超出这里所涵盖的材料的指导的人提供一个非常有用的资源。本指南当然不是详尽无遗的,但是应该可以让你用一个好的工作流开始并运行 R!

1。 安装软件

首先,您需要安装 R 和 RStudio!

r 下载链接:https://cloud.r-project.org/

从这里,选择您的操作系统并选择最新版本。

RStudio 下载链接:https://rstudio.com/products/rstudio/download/

从这里,选择免费的 RStudio 桌面选项。

2。 熟悉 RStudio

打开 RStudio,这应该是您看到的屏幕:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

你在看什么?

蓝色的是您的控制台—您可以在这里运行不会作为脚本的一部分保存的代码(您可能希望使用此选项来安装一个包,或者快速查看一个表),在这里您将看到有关您已经运行的代码以及您可能收到的任何错误的信息。其他选项卡允许您访问您的终端和作业,但是随着您对 r 的熟悉,您将很少使用这些选项卡。

绿色的是环境。您创建的任何命名实体(如数据帧、向量、函数)将在此显示。通常,您可以单击环境中的内容进行查看,这在您加载外部数据并对其进行清理时非常有用。小扫帚图标可以用来清空这个环境。一旦我们设置了 git 和到 GitHub 的连接,这里也会看到一个“Git”标签。

红色是一个查看器窗格。目前它在“包”标签上,允许你看到什么包被安装在本地。带有勾号的是当前加载的。根据 RStudio 设置,代码输出可能会显示在“绘图”和“查看器”选项卡中。您可以在“帮助”标签中搜索软件包名称以获得有用的信息。

3。 文件类型

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我将要经历的工作流尽可能利用 R Markdown 文件,但是我想快速介绍 R 脚本和闪亮的 Web 应用程序。

剧本:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

脚本是用 R 编写代码的最基本的文件类型,通常用于存储最终将被部署的函数或其他代码。即使您在开始使用 R 时能够选择独占 R Markdown 用法,您也会经常收到来自他人的脚本代码,熟悉这种格式很重要。如您所见,蓝色框中包含的是一个新面板,现在您已经在脚本中了。这是您可以输入代码的地方。

我已经创建了三个命名值:“x”、“y”和“sum”,这是 x 和 y 的总和。由于这三个都是命名的,所以可以在环境面板中找到它们及其相关的数值。

看一下控制台。

当我运行这三行代码时,前三条蓝色的线出现了——它们只是表明代码已经运行了。

在第四行,我直接在控制台中键入“x + y”并按下“enter”下面的黑色文字提供了这个等式的答案。因为这只是在控制台中输入的,所以输出不会保存在任何地方,也不会影响脚本。

试着复制我这里非常简单的代码。你可以通过点击“运行”按钮来运行代码,或者在 Mac 上同时按下 command + return 键(对于 Windows,按下 control + enter )。

闪亮:

我不打算解释如何创建闪亮的应用程序,因为一旦你相当熟悉 R 语言编码,这是一个需要解决的问题,但是知道它们的存在是很好的。Shiny 允许您创建交互式仪表板,是一个非常好的数据可视化工具。您可以通过 RStudio 的服务器公开托管仪表板,将它们嵌入网站等等。

如果你感兴趣,这里有一些关于 Shiny 的进一步信息:https://shiny.rstudio.com/

R 降价文件:

使用 Markdown 文件是创建可重复的、可理解的代码的重要工具。除了编写代码的实际 Markdown 文件之外,您还可以将它“编织”成一个易于阅读的输出文件(我将解释这是什么意思),即使没有安装 R 也可以打开它。您可以从下面的气泡中选择想要的输出类型(HTML、PDF 和 Word)。我喜欢坚持使用 HTML,因为它格式好,允许在线共享,但我经常为最终报告创建 pdf,与数据分析团队以外的同事共享。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

继续点击“确定”!这是您接下来应该看到的内容:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

你在看什么?

蓝色是您的 YAML 标题,上面有您刚刚输入的信息。想要更改标题、日期或输出类型吗?通过编辑与标题、作者和日期相关联的引号之间的文本,以及将“html_document”替换为“pdf_document”或“word_document”,您可以很容易地做到这一点如果您对在输出文件中列出标题、作者或日期不感兴趣,您可以简单地删除相关的行。

绿色的是代码块。您的所有代码都将包含在代码块中。代码块都遵循以下格式:

```{r chunk_name, specifications}```

可以通过 option + command + i 快捷键(Windows 上, control + Alt + i )在 MAC 上直接插入代码块。您可以通过按块右上角的绿色箭头来运行单个代码块。

给你的代码块命名是一个好习惯。这对可能使用您的代码的任何人都很有用,也有助于在您的代码产生错误时有效地进行故障排除。您希望对代码块命名使用与变量命名相同的准则:唯一的、描述性的、不带空格。例如,您可能有名为“数据导入”、“数据清理”、“分析”和“绘图”的代码块。

您可以使用多种规范来更改任何给定代码块中的代码在输出文件中的显示方式,下面提供了一些最常用的规范:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

https://p8105.com/writing_with_data.html 杰夫·戈德史密斯的名单

红色的是标题。您可以使用井号来确定输出文件中文件头的大小,每增加一个“#”会使文件头变小:

# Main Heading
## Subheading 1
### Subheading 2

灰色是常规文本,它将在输出文件中显示出来。好的 Markdown 文件通常有大量的文本来帮助其他人理解你的代码,使它更容易理解。文档记录良好的代码也将使您在以后回过头来看自己的代码时更容易理解!

知道可以加粗和斜体文本以及添加内联代码是很有用的:

*bold*
**italicize**
`r desired_inline_code`

一个有用的使用和格式化 R Markdown 文件的备忘单可以在这里找到:https://R studio . com/WP-content/uploads/2016/03/rmarkdown-cheat sheet-2.0 . pdf

橙色的是“编织”按钮——这就是你创建输出文件的方式!只有在代码中没有错误的情况下,文件才会被编织,因此编织也是检查工作的一种有用方式。现在尝试单击“编织”按钮,看看示例代码在输出文件中的样子。

4。 工作流和 Git

有效地、可重复地使用 R 的一个基本技能是拥有一个清晰的、标准化的工作流程。我将在这里使用 GitHub 演示一个,当你在 r 中工作时,你应该总是使用一致的工作流程。

Git 和 GitHub 是版本控制和代码共享的常用工具。为了开始,你需要在 GitHub 上创建一个免费账户:https://github.com/

接下来,您需要验证 git 是否已经安装并准备好在您的计算机上运行。为了做到这一点,你应该遵循这个指南:https://happygitwithr.com/install-git.html(尽管如果你愿意,你可以使用 RStudio 中的 terminal 选项卡而不是 shell 来遵循 6.1 中的说明——我发现这要容易得多)。

现在,您应该按照以下工作流程进行配置:

  • 创建一个有意义命名的 GitHub 库
  • 在 R 中创建新项目,并将其链接到此回购
  • 将所有相关文件存储在该项目文件夹中,并使用有意义的命名、一致的子文件夹(如存储所有数据的“数据”文件夹)
  • 使用 R 中的 Git 选项卡来一致地编织、提交和推送

让我们走一遍:

一、创建一个有意义命名的 GitHub 库

在 GitHub 中,点击存储库,然后点击新建:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在那里,您可以为您的 repo 命名并进行简要描述。这个报告包含了使用在线聊天数据的第二阶段研究的数据,因此被命名为“chat_phase_2”我知道这个名字将允许我在几个月后再次使用它时找到回购协议,并且我的合作者也将能够跟踪它。

您的回购可以是公开的(任何人都可以找到您的回购及其内容),也可以是私有的(只有您和指定的合作者可以看到它及其内容)。公开回购有许多很好的用途(例如,共享您创建的包,共享您创建的酷项目),但如果您正在使用包含机密信息的数据和/或正在进行尚未发表的研究,您总是希望使用私人回购。您可以在以后更改这些名称,但是应该始终小心您公开的信息。

通常,您会希望创建一个自述文件,以指导您自己和其他任何可能通过其内容访问您的 repo 的人。一份好的自述文件概述了你的报告的内容,并为你所做的工作提供了简要的理由。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

单击“创建存储库”,然后复制将出现在以下页面上的链接:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

二。在 R 中创建新项目,并将其链接到这个 repo

在 R 中,单击文件→新建项目

接下来,选择“带有版本控制的项目”:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

选择 Git:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后,将您从 GitHub 复制的 URL 粘贴到 Repository URL 下,然后单击“创建项目”。我已经在我的桌面上创建了我的项目文件夹,但是你可以在你电脑的任何地方浏览创建你的项目。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

项目应该在 r 中打开。您将知道它工作了,因为您的项目将在屏幕的右上角显示为打开的项目,并且您现在将在右上角面板中有一个“Git”选项卡。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

三世。将所有相关文件存储在该项目文件夹中,并使用有意义的命名、一致的子文件夹(如存储所有数据的“数据”文件夹)

既然您已经创建了一个本地项目和一个 GitHub repo,那么您会希望在进行过程中保持它们的整洁和有序。

我将数据添加到数据文件夹中的项目中,因此我当前的项目文件夹如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

随着我的进展,任何额外的数据都将以一致的文件名添加到这个“数据”文件夹中,我将为我创建的任何重要图表或其他输出创建一个“输出”文件夹,并且我将有几个故意划分的 R Markdown 文件。例如,我可能有一个用来清理数据的 Markdown 文件,一个用来执行分析,一个用来生成可视化。

四世。使用 R 中的 Git 选项卡一致地编织、提交和推送

GitHub 只对版本控制有效,如果你坚持把你的工作推给他们的平台。为此,请点击 RStudio 中的“Git”选项卡。每当您对本地项目进行更改时,它们都会出现在该选项卡下。首先,单击自上次更新回购以来所做的所有更改。接下来,单击“提交”按钮。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

您需要输入一条提交消息来描述您所做的更改。这使得其他人可以更容易地浏览您的回购协议,如果您以后需要访问它,也可以更容易地找到您代码的以前版本。

输入提交消息后,选择右下角的“提交”。如果运行无误,就可以使用“按钮”了。点击“推送”将您的更新发送到 GitHub。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在你所有的修改都备份在 GitHub 上了!你会希望在工作中坚持这样做。我建议你第一次这样做的时候检查一下你的 GitHub 账户,看看你的作品是如何存储在那里的。如果你正在访问别人的回购,或者别人对你的回购做了更改,你可以使用“拉”将最新版本的回购拉至你的电脑。

5。 装载包裹

现在一切都设置好了,您可以开始在 R 中工作了!

首先,打开一个新的 R Markdown 文件。如果您在项目打开时单击“文件”→“新建文件”→“R Markdown ”(同样,如果您的项目的名称出现在窗口的右上角,您就可以知道该项目是打开的), R Markdown 文件将会在您的项目中自动创建。

R 自动带有“base R”函数。然而,R 是开源的(这意味着任何人都可以贡献包),并且有许多令人惊奇的包,你将需要有效地使用 R。您必须一次性安装这些软件包,然后在每次需要使用它们时加载它们。下面提供了这样做的代码(注意双引号表示安装包,单引号表示加载包)。我喜欢在控制台中安装包,因为我只需要这样做一次,因此没有理由保存安装包的代码行。您将在控制台中看到确认信息,表明软件包已正确安装和加载。

install.packages("tidyverse")
library('tidyverse')

注意:Tidyverse 实际上是包的集合而不是单个包。我强烈建议您熟悉 tidyverse 及其包含的软件包。它们被广泛使用和流行,因为它们会让你的生活变得无限简单——我每次创建一个新的减价文件时都会自动加载它。你可以在这里找到更多关于 tidyverse 及其组件包的信息:【https://www.tidyverse.org/

6。 其他注释

r 是区分大小写的,不像 SAS 和其他一些语言。这种区分大小写是使用一致的文件和变量命名结构如此重要的原因之一——您的代码中不太可能出现令人讨厌的错误,其他查看您代码的人也更容易理解它。我个人是专门用 snake case(everything _ is _ lower case _ with _ understand)的。

对于如何格式化代码,也有既定的指导方针。你应该努力让代码不仅运行,而且整洁!哈德利·韦翰的一本有用的时尚指南可以在这里找到:http://adv-r.had.co.nz/Style.html

7。 启动运行!

现在,您应该能够打开一个新的 R Markdown 文件,作为有意工作流的一部分,并在该文件中安装和加载包。这些技巧可以让你更好地利用精彩的教程,而不是带你在 r 中导入、清理、分析和可视化数据。

使用 R 分析我的 Strava 数据

原文:https://towardsdatascience.com/using-r-to-analyse-my-strava-data-fc57188b4c51?source=collection_archive---------23-----------------------

使用 Strava 数据学习 R 的初学者之旅

有了这些空闲时间,我决定花相当多的时间来提高我的统计知识和编程技能。作为一名数据分析师,我每天都使用 SAS 和 SQL,但目前没有使用更高级的 R -这对于可视化、更高级的统计分析和机器学习非常有用。考虑到提高上述技能的愿望,我决定 R 是实现我的目标的一个好起点。

因为没有像现在这样的时间(确切地说是此刻),我要陷进去!

入门

首先,分析什么?当然,我可以在网上找到一些东西,有很多有趣的新冠肺炎数据集可以开始使用。然而,对我来说,当学习新的东西时,有一定程度的熟悉是好的,这样手头的任务看起来就不那么令人生畏了。在这种情况下,这种熟悉的形式是我的数据集;我过去 5 年的斯特拉发活动的输出。那就是 355 次跑步,7 次循环和 3 次游泳(对我喜欢的项目有什么猜测吗?如果我要在今年完成我的铁人三项的话,我也许应该多学学另外两项。).使用我自己的数据集对我来说很重要,因为如果我犯了错误,如果我知道并理解数据,我更有可能发现它。显然,在处理庞大的数据集时,情况并不总是这样,但当我是一个完全的 R 新手时,这是一个很好的起点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Strava 数据样本(36 个变量中的 7 个)

虽然我通常会为我试图利用数据实现的目标设定目标(以便提供清晰性和方向),但在这种情况下,我已经偏离了轨道,虽然我已经熟悉了 R,但我的主要目标只是更好地理解该计划,同时希望得出一些有趣的见解。

因为我以前从未使用过 R,所以我在谷歌上搜索了一些初学者教程。我发现对 R and R 工作室的介绍真的很有用,也很容易理解。我没有像班上其他人一样使用样本数据集,而是使用我自己的数据,只是将我自己的变量和字段应用于函数,而不是导师给的那些。这是一个开始适应 R 的好地方,经过几个小时的基础学习,我觉得已经准备好开始构建自己的见解了。

完全公开,我肯定还在掌握 R,但我想分享我的想法和迄今为止我创造的情节的发现。

直方图

我制作的第一个图表是这个直方图。这相对容易做到(图片下面的代码),但它很好地显示了我在每个框中的活动频率。如你所见,我绝大多数的活动都是 5 公里。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

活动距离直方图

#Histogram
hist(strava2$Distance, breaks = 21, main = "Histogram of Activity Distances", xlab = 'Distance (KM)')

散点图

然后我转向散点图,这花了我一段时间,主要是因为我在处理日期,这被证明是一个巨大的痛苦。我从 Strava 下载的 CSV 文件将活动日期生成为带有时间戳的日期,格式为 Jan 01,2016,07:30:00’,并作为字符传递给 R。您可能会认为转换成 date 类很简单,但是由于最后的时间戳,这就不那么简单了。在花了几个小时试图解决这个问题之后,我真的快要放弃了,用 Excel 来修改原始数据,这样可能会快得多。然而,我坚持了下来,并最终使用了“mutate”函数。我不确定我是否把这个问题复杂化了——我认为众所周知,时间序列数据在大多数程序中很难处理——但是我欢迎任何关于处理这个问题的最佳方法的想法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

活动散点图

我喜欢这个情节的输出。这是一个很好的方式来展示这些年来我的行为是如何改变的。这个图表非常清楚地表明,从 2018 年开始(大约是我第一次使用 Garmin 的时候),我的活动频率显著增加。你可以看到相当多的活动都在 5 公里左右。你还可以看到,从 2019 年年中开始,游泳和骑行开始出现在图表上(就在我进入我的铁人三项之后!).

#Remove time from the date/time timestamp
strava2 <- strava2 %>%
    mutate(Activity.Date = as.Date(Activity.Date, format='%B %d, %Y, %H:%M:%S'))#Scatter Plot 
    ggplot(data=strava2, aes(x = Activity.Date, y = Distance, colour = Activity.Type)) +
        geom_point() +
        theme_bw() +
        theme(legend.position = "bottom", legend.title = element_blank())+ 
        theme(plot.title = element_text(hjust = 0.5))+
        labs(title = "Activities",
             colour = "Activity.Type",
             y = "Distance (KM)",
             x = "Date" + theme_bw(base_size = 15))

方块剧情

盒须图。这也不是太难(感谢 Stack overflow 上丰富的论坛、网站和帖子)。我可以花一些时间在颜色和格式上,但是为了节省时间,我放弃了。我发现 T4 的网站对颜色选择很有用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

按活动类型划分的距离箱线图

你在这里可以看到,与跑步相比,游泳框图相对较短(尽管数据集中只有少数游泳)。这表明我的游泳距离相似,而我的跑步距离相差更大。

我跑步的四分位数范围(中间 50%的数据)在 5 到 7 公里之间。这意味着我跑的 50%的距离在 5-7 公里之间。

#Boxplot 
boxplot(Distance~Activity.Type,
            data=strava2,
            xlab="Activity Type",
            ylab="Distance (KM)",
            cex.lab=0.75,
            cex.axis=0.75,
            col="lightsalmon",
            border="lightsalmon3"
    )

柱状图

我想将我的数据分组,以便按月份和年份查看趋势。我最初认为按月计算我每天的路程会很困难,但惊喜地发现这相当简单。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

按月的距离条形图

这是一个很好的图表,可以快速提取见解并讲述一个故事。从 2019 年初开始,我可以看到我的活动有所减少,特别是在我受伤的 2 月份。我还可以看到 2020 年 3 月我的总距离出现了巨大的峰值,当时我们被告知在家工作,并进入了锁定状态,这意味着更多的时间和锻炼的需要。我在 4 月初导出了这些数据,但我认为,到月底,4 月的数据会比 3 月的数据更高,因为跑步是我在禁闭期间的主要安慰来源之一。

有趣的是,看到每年七月我的活动量显著下降。起初这有点令人惊讶,但当我仔细想想,这是有道理的。首先,7 月份是我的生日,其次,在过去连续三年(2017-19 年)里,我一直是我姐姐和我两个最好朋友 7 月份婚礼的伴娘,而且(有时)天气很热,比起长跑,我更想在外面喝点杜松子酒。所有这些因素意味着跑步可以而且已经退居二线(相当正确)。然而,我敢打赌,如果我画出活动的数量(而不是距离),它看起来不会有太大的不同。我想这与其说是因为我不经常跑步,不如说是因为我跑的距离更短(我的意思是,当气温为 25 度,并且可以与家人和朋友一起享受乐趣时,谁会愿意跑 15 公里呢?不是我)。

#Bar Plot
    barplot(t(rowsum(strava2$Distance,
                     format(strava2$Activity.Date,"%Y-%m"))), 
            las=2, col = "darkolivegreen3",
            cex.lab=0.75, cex.axis=0.75, cex.names = 0.75,
                    xlab="Month",
                    ylab= "Distance (KM)"
                    )

总结

我在这里主要关注的是距离,但还有很多可以做的。我想接下来我会研究我跑步的速度,以及它是如何随着一天的时间、季节、年份等变化的。例如,我可以研究我是否更有可能在早上、下午或晚上跑得更快,以及这是否有意义。

这很有挑战性,但我真的很喜欢开始使用 R,我期待着很快用它做更复杂的分析。

使用 R 分析我的 Strava 数据:第 2 部分

原文:https://towardsdatascience.com/using-r-to-analyse-my-strava-data-part-2-9124b1955b27?source=collection_archive---------54-----------------------

在我的第一篇博文中,我讨论了想要学习 R 的原因,并分享了我在掌握该软件的前三周内所取得的成就。在这篇文章中,我将继续阐述我所学到的东西和我所遇到的更多困难,并希望与其他 R 初学者分享一些有趣的见解和有用的技巧。

这里提醒一下我的数据集中的一些变量。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Strava 数据样本

累积线状图

首先是累积线图,它显示了我从 2017 年开始的距离的累积和。很高兴看到 2020 年有了一个良好的开端(在运动方面!).

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

每年累积距离

由于这个输出需要将多个操作串在一起,管道操作符(来自 dplyr 包)真的派上了用场,它可以帮助跟踪我正在做的事情,因为它以逻辑步骤来布局代码。管道操作符实际上翻译成‘然后’。所以在下面的例子中,我说:获取我的 Strava 数据集**,然后**按年份分组,然后按活动日期的顺序排列,然后将距离变量突变为该年距离的累积和,等等。这可以在没有管道操作员的情况下完成,但在我看来,这样做要干净得多,也更容易阅读。

#Cumulative distance per year
cum_plot <- strava2 %>%
    group_by(year) %>%
    arrange(Activity.Date) %>%
    mutate(cumulative_distance = cumsum(Distance)) %>%
    ungroup() %>%
    filter(year >= 2017) %>%
    ggplot(aes(x = day_of_year, y = cumulative_distance, color = factor(year))) +
    geom_line() +
    scale_color_brewer(palette = "Dark2") +
    theme(legend.position = "bottom") +
    #theme(panel.background = element_blank())+
      labs(title = "Cumultative Distance (KM)",
           y = "Distance (KM)",
           x = "Day of Year",
           colour = "Year")

这个视频解释了如何使用管道操作符,以及 dyplyr 包中最有用的函数(选择、过滤、排列、变异、总结和分组)。我曾多次提到它,并向其他刚开始在 r 的人推荐一款手表。

小提琴剧情

在我的上一篇博客文章中,我展示了一个按活动类型划分的方框图,但鉴于我原本打算在 8 月份进行的伦敦铁人三项赛最近被推迟到 2021 年,并且由于数据中明显缺乏周期和游泳,我认为可能值得只为跑步做一个变化的方框图。

进入小提琴情节。这个图的小提琴形状来自于数据的密度。较厚的部分意味着小提琴该部分的值具有较高的频率,而较薄的部分意味着较低的频率。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

按月距离的小提琴图

事实上,六月和七月的小提琴比其他月份短得多,宽得多,这证明了我的假设,即在夏季,我更有可能进行短途旅行。

#Violin plot
strava_runs <- filter(strava2, Activity.Type == “Run” )
 ggplot(strava_runs, aes (x = calendar_month, y = Distance, fill = calendar_month)) +
 geom_violin() +
 scale_fill_brewer(palette=”Set3") +
 theme(legend.position=’none’) +
 labs(y = “ Distance (KM)”,
 x = “Month”)

由于我的行为按月有明显的不同,我决定把我的跑步按季节分组是值得的。这个变量并不在我的数据集中,所以我使用了一个“case when”语句将每个月归入各自的季节。

#Runs by season
 strava2 <- strava2 %>% mutate (Season = case_when (
 calendar_month %in% c(“Mar”, “Apr”, “May”) ~ “Spring”,
 calendar_month %in% c(“Jun”, “Jul”, “Aug”) ~ “Summer”,
 calendar_month %in% c(“Sep”, “Oct”, “Nov”) ~ “Autumn”,
 calendar_month %in% c(“Dec”, “Jan”, “Feb”) ~ “Winter”,
 TRUE ~ “Others” ))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

就像我之前说的,夏天不适合长跑!

密度脊

在与一位朋友分享了我之前的博客后,他指出,鉴于我的一些图表中显示的 5 公里活动的集中程度,我的数据集中可能存在跑偏。我认为情况很可能是这样;数据集内 355 次运行中的 70 次(20%)是停车运行-运行。

这一观察让我想到,按照一天中的小时和一周中的天来可视化我的跑步,来可视化我的数据集**中 Parkrun 的普遍性,这将会很有趣。**对密度脊线图进行排队,这是显示特定组的数值分布的理想方式,在本例中,为星期几和一天中的小时。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

按一周中的每一天和一天中的每一小时分配活动

周六上午 9 点的高峰是显而易见的,我显然是一个超级 Parkrun 粉丝!我还发现很有趣的是,在周一早上,我不太可能锻炼,而在周五和周六晚上,你同样不太可能发现我在跑步(不言自明)。从美学的角度来看,我喜欢这张图,但密度脊可能会对这样的数据产生误导,所以事后来看,条形图或直方图可能是更好的选择,因为它们不会平滑点之间的数据。

这个图花了一段时间才完成,主要是因为 Strava 数据下载的日期和时间戳有更多的问题。一旦我解决了如何将时间从 12 小时制转换为 24 小时制,我就回到了正轨,但在按照逻辑顺序安排一周中的日子时遇到了一些小困难(我对其他有类似问题的人使用了“因子”和“级别”)。

我选择了柔和的配色方案,但在 Brewer palette 中有许多不错的调色板,在这里可以找到。

# Density Ridges
 density_ridge <- strava2$wday <- factor(strava2$wday, levels = c(“Sun”, “Sat”, “Fri”, “Thu”, “Wed”,”Tue”,”Mon”)) 
 ggplot(strava2, aes(x = Hour, y = wday, fill = wday )) +
 geom_density_ridges(scale = 1.1) +
 theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank())+
 scale_x_continuous(breaks=seq(0,24,2)) +
 scale_y_discrete(expand = c(0.01, 0) , labels = c(“Sun”, “Sat”, “Fri”, “Thu”, “Wed”,”Tue”,”Mon”))+
 theme(axis.text=element_text(size=rel(0.8))) +
 theme(legend.position=’none’) +
 scale_fill_brewer(palette=”Pastel2") +
 ylab(NULL)

几何十六进制

当数据集中有大量数据点时,这种类型的图对于表示两个数值变量(在本例中为经过的分钟数和距离)的关系非常有用。不是重叠,而是将绘图窗口分割成几个‘六边形格’,并计算每个六边形格的点数。颜色表示这个点数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

按距离划分的已用分钟数的几何十六进制曲线图

正如我在其他图表中展示的那样,活动主要集中在 5 公里范围内。但是该图增加了一个额外的维度,显示了经过的分钟数,您可以清楚地看到,大多数活动都在 5 公里的距离内,大约需要 25 分钟。然而,在这个图中丢失的是我的 5 公里跑所用时间的变化;25 分钟和 22 分钟的 5000 米之间的差别非常显著,我觉得这一点在这里被忽略了。

#Geom hex
 filter(strava2, Activity.Type == ‘Run’ & Elapsed.Mins < 150) %>%
 ggplot(aes(x = Distance, y = Elapsed.Mins)) + 
 geom_hex() + scale_fill_distiller(palette = “Spectral”) +
 labs(y = “Elapsed Minutes”,
 x = “Distance (KM)”) +
 theme(panel.background = element_rect(fill = “white”),
 panel.border = element_rect(colour = “lightgrey”, fill = NA, linetype = 1, size = 0.3),
 panel.grid.major.x = element_line(colour = “lightgrey”, linetype = 3, size = 0.3),
 panel.grid.major.y = element_line(colour = “lightgrey”, linetype = 3, size = 0.3)

创建主题

正如你在上面的代码中看到的,我在很多文本中格式化了情节的小细节。然而,作为一个 R 新手,我最近发现了一些我认为可以节省大量时间的东西。这就是创建你自己的主题的能力,这样你就不必在每次创建一个情节时改变你的视觉化的小细节(游戏改变者!).如何创建自己的主题在这段视频中解释得非常清楚。

这是我的主题示例:

#Create my own theme
 theme_rosie <- function() {
 theme(
 # add border 1)
 panel.border = element_rect(colour = “lightgrey”, fill = NA, linetype = 1),
 # color background 2)
 panel.background = element_rect(fill = “white”),
 # modify grid 3)
 panel.grid.major.x = element_line(colour = “lightgrey”, linetype = 3, size = 0.5),
 panel.grid.minor.x = element_blank(),
 panel.grid.major.y = element_line(colour = “lightgrey”, linetype = 3, size = 0.5),
 panel.grid.minor.y = element_blank(),
 # modify text, axis and colour 4) and 5)
 axis.text = element_text(colour = “black”, family = “Arial”),
 axis.title = element_text(colour = “black”, family = “Arial”),
 axis.ticks = element_line(colour = “black”),
 # legend at the bottom 6)
 legend.position = “bottom”
 )
 }

平滑线散点图

在过去的几个月里,我感觉自己比以往任何时候都更有规律地跑步,尽管如此,还是有很多天我发现跑步真的很难,即使是在我以通常感觉舒适的速度跑步的时候。一个人跑步时的感觉取决于许多因素,但我认为值得做一个基本测试,将我的距离总和与我每月的平均时间进行比较,看看这两个变量之间是否有任何相关性。我试图回答的问题是:你投入的越多(就距离而言),你就越能以更快的速度获得更多的回报,还是事实上当你投入更多时,你会发现自己很疲劳,因此跑得更慢?

显然,有很多因素会影响你的速度,从温度到一天中的时间等等,更不用说你还做了什么其他的健身运动,比如交叉训练和速度训练。然而,为了这个练习的目的,我只关注了我每个月的总距离,仅仅是我的 5 公里跑。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

有趣的是,看起来我每月跑的 5 公里越多,我的平均时间就越慢。所以说到跑步,总的来说,我投入的越少,出去的就越多。虽然这可能不是我生活的座右铭…

#Filter, group and summarise: 5K Runs
five_k_runs <- strava2 %>% 
 filter(Activity.Type == ‘Run’, Distance_Rounded == 5, Elapsed.Mins < 70) %>%
 group_by(year, calendar_month) %>% summarise (Sum_Distance= sum(Distance_Rounded), Avg_Time = mean(Elapsed.Mins), Num_Runs = length(Activity.ID))
 #create plot
 avg_5k_by_month <-
 five_k_runs %>%
 group_by(year) %>%
 ungroup() %>%
 filter(year >= 2018, year <= 2019) %>%
 ggplot(aes(x = calendar_month, y = Avg_Time, color = factor(year))) +
 geom_point(aes(size = Sum_Distance)) +
 guides( size = FALSE) +
 scale_color_brewer(palette = “Dark2”) +
 theme(legend.position = “bottom”) +
 labs(y = “Avg 5K Time (Minutes)”,
 x = “Month”,
 colour = “Year”) +
 geom_text(aes(label=Sum_Distance),hjust=2, vjust=2, size = 3)
 #apply theme
 avg_5k_by_month + theme_rosie()

总结

我确信我只是触及了可以做的事情的表面,但是使用 R 来分析我的 Strava 数据是一项非常有价值的活动,原因有很多。

首先,它让我对自己的训练有了更深刻的认识。这是我想强调的地方,比如夏季的长距离跑和冬季的长距离跑。这让我想在增加距离方面更进一步——我能经常跑 5 公里以上吗?这让我开始考虑天气数据和跑步后情绪跟踪等额外信息如何为我的洞察力增加额外的维度。这激励我继续努力工作。

就学习 R 本身而言,这是一个很好的方式来更好地理解它是如何工作的,以及 if 必须提供什么。这让我意识到 R 实际上并不像我预期的那么难学,但也让我更加确信你花时间去练习是很重要的。就个人而言,我认为使用你感兴趣的数据集是一种非常愉快的学习方式。无论是 Strava,英超联赛统计数据还是你的 Spotify 收听历史,如果你觉得有趣,它更有可能让你有动力继续下去。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值