R练习50题 - 第一期

2020-08-12 10:49:50 浏览数 (1)

在前面

从这期开始,大猫课堂将会推出一个新的系列:R练习50题,目的是使用50道练习题让大家掌握常用的数据操作,例如寻找每组最大的N个观测等。本练习题来源于Renkun (github.com/renkun-ken/r-data-practice) 在Github上的共享,我们认为它包括了绝大多数实践中会遇到的问题,特别具有代表性。只可惜Renkun并没有提供答案,所以我们在这里提供我们的版本。

我们的所有答案都将使用data.table这个包。我们认为data.table是最优秀的数据处理工具,没有之一。关于data.table的神奇之处以及它和其他工具(例如pandas)的比较,欢迎大家戳它的官网:github.com/Rdatatable/data.table.

拥有data.table的基础会有助于你更快看懂答案,但并非必要。我们会在讲解答案的时候穿插data.table的教学。关于data.table的入门,我们认为最好的教材是它的Github Wiki( github.com/Rdatatable/data.table/wiki)。

我们已经把所有50题的答案都上传到了我们的Github主页,等不及想先睹为快的同学,请猛戳这里:

github.com/Ravin515/r-data-practice

据集预览

所有50道练习题都基于同一个股票价格数据集而设计。虽然具有明显的金融背景,但是它和其他学科所遇到的数据集是相通的:在我们的数据集中,每个股票代码symbol和日期date的组合都决定了唯一的一个观测,相当于数据集的key,这种由“横截面”与“时间序列”共同组成的“面板数据”在工作中几乎随处可见。

我们首先使用以下代码导入数据集:

代码语言:javascript复制
# We only need two packages here 
library(data.table) 
library(stringr) 
# set `data_path` to your dir 
data_path <- "C:/Users/rossz/OneDrive/App/R/stock-datatable-key/data" 
setwd(data_path) 
# read into data 
data <- readRDS("stock-market-data.rds") data[1:5] # show top 5 obs

我们给出数据集前五行的预览:

值得说明的有一下几点:

  • 数据集为“面板数据”:包含多个股票(横截面),而每个股票则有多个按照日期排序的变量(时间序列)
  • 股票代码symbol 和日期date共同组成了数据集的key,也即每个唯一的symbol 和date组合决定了一个唯一的观测。
  • 整个数据集首先按照代码symbol排列,其次按照日期date排列。
  • 若干主要变量说明:
    • symbol:股票代码。.SH 结尾的是沪股,.SZ 结尾的是深股
    • date:日期
    • pre_close:昨收盘
    • open:开盘价
    • high:最高价(日内)
    • low:最低价(日内)
    • close:收盘价
    • volume:成交量
    • amount:成交金额
    • industry:行业

习1:哪些股票的代码中包含"8"这个数字?

问题分析

首先,我们需要把股票代码symbol中包含8的那些观测找出来。我们可以借助与stringr这个字符串处理包。这一步不难,稍微有些挑战的是去重。如果我们不去重,那么我们会得到非常多的重复观测。例如股票600128,如果它一共有100天的观测,那么我们会出现100个重复结果。为了去重,我们需要借助于data.table中的unique函数。

我们希望最终的输出是一个字符串向量:

代码

data[str_detect(symbol, "8"),

unique(symbol)]

  • str_detect函数来自stringr包,它的输入是一个char vector,输出则是boolean vector,长度与原向量相同。str_detect(symbol, "8")含义为:对于symbol向量,判断其是否含有字符8,如果有,则为True,否则Faulse。
  • unique:找出symbol中不重复的值。
  • 在data.table的语法中,先进行列选择操作,再对列进行处理。所以上述语句会先执行str_detect,再执行unique

练习2:每天上涨和下跌的股票各有多少?

问题分析

这一题需要引入分组的概念,并且按照“先分组,后统计”两步走。首先按照题意,我们需要为每个交易日date建立一个“组”。其次,对于每个组,我们需要生成两个统计数字:一个统计上涨的个数,一个统计下跌的个数。最终结果如下:

可以看到,对于每个date,它都对应了两个观测,一个是“UP”,一个是“DOWN”。

代码分析

代码语言:javascript复制
data[, 
        .(num = uniqueN(symbol)), 
    keyby = .(date, updown = ifelse(close - pre_close > 0, "UP", "DOWN"))]

  • 代码第一行只有一个逗号。这是因为data.table的第一个语句用来对列进行选择,由于我们这里需要对所有列进行统计,所以不需要进行任何操作。
  • keyby用来进行分组,是整个代码的核心。先来看keyby = .(date, updown)这个结构,他的意思是,把整个数据集按照date和updown两个变量进行分组,并依次排序。其中,updown是我们新建的字符变量,用来表示分组,它只取两个值:UP, DOWN。这其中的难点是建立updown这个变量。我们使用了ifelse这个函数。ifelse(close - pre_close > 0, "UP", "DOWN")的意思是,如果今天的收盘价高于昨天的收盘价,那么取值UP,反之取值DOWN。
  • 代码第二行生成了一个新变量num。由于在keyby语句中我们已经按照日期与涨跌进行了分组,所以这一步我们只需要统计每个组有多少个股票就可以了。我们在这里使用了uniqueN这个函数。它是data.table内置函数之一,和unique几乎执行相同的操作,唯一不同的是,unique返回的是不重复的item(是一个向量),而uniqueN返回的是不重复的数量(是一个数字)
  • 整个代码的执行顺序是:先选择行(逗号空白行),再分组(keyby语句),最后进行组间统计(num语句)。
  • 我们的答案中,行、列以及分组三条语句各占一行,实际上这仅仅是为了让代码更直观。如果你愿意,data.table允许你把所有的代码都写在同一行,就像这样:

期预告

在下一期,我们会继续带来剩余题目的解答~

大猫的R语言课堂

我是大猫,一个高中读文科但却在代码、数学的路上狂奔不止的Finance Ph. D Candidate。

我是村长,一个玩了9年指弹吉他,却被代码深深吸引的博士候选人。

大猫的微信号是:

iRoss2007

村长的B站主页是:http://space.bilibili.com/40771572

大猫的R语言课堂关注R语言、数据挖掘以及经济金融学。

我们与大家分享我们的知识和节操,我相信独乐乐不如众乐乐。

0 人点赞