前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >「R」数据操作(二)

「R」数据操作(二)

作者头像
王诗翔呀
发布2020-07-06 17:23:05
7060
发布2020-07-06 17:23:05
举报
文章被收录于专栏:优雅R优雅R

这里数据虽然已经没有了缺失值,但每一行数据的含义却发生了变化。原始数据中产品T01在20160303这天并没有测试,所以这一天的值应该被解释为在此之前的最后一次quality的测试值。另一个问题是两种产品都是按月测试的,但重塑后的数据框没有以固定的频率对其date。

下面方法进问题进行修正。

代码语言:javascript
复制
toy_tests$ym = substr(toy_tests$date, 1, 6)
toy_tests
#> # A tibble: 8 x 6
#>   id        date sample quality durability ym    
#>   <chr>    <int>  <int>   <int>      <int> <chr> 
#> 1 T01   20160201    100       9          9 201602
#> 2 T01   20160302    150      10          9 201603
#> 3 T01   20160405    180       9         10 201604
#> 4 T01   20160502    140       9          9 201605
#> 5 T02   20160201     70       7          9 201602
#> 6 T02   20160303     75       8          8 201603
#> 7 T02   20160403     90       9          8 201604
#> 8 T02   20160502     85      10          9 201605

我们只提取年月信息,然后利用它进行重塑。

代码语言:javascript
复制
toy_quality = dcast(toy_tests, ym ~ id, value.var = "quality")
toy_quality
#>       ym T01 T02
#> 1 201602   9   7
#> 2 201603  10   8
#> 3 201604   9   9
#> 4 201605   9  10

现在,两种产品每月的质量得分自然地展示出来,而且每月缺失值。

有时候,我们需要将许多列合并为1列,用于表示被测量的对象,另外用1列存储对应的结果值。下面用melt()函数将原始数据两种测量组合到一起:

代码语言:javascript
复制
toy_tests2 = melt(toy_tests, id.vars = c("id", "ym"), 
                  measure.vars = c("quality", "durability"),
                  variable.name = "measure")
toy_tests2
#>     id     ym    measure value
#> 1  T01 201602    quality     9
#> 2  T01 201603    quality    10
#> 3  T01 201604    quality     9
#> 4  T01 201605    quality     9
#> 5  T02 201602    quality     7
#> 6  T02 201603    quality     8
#> 7  T02 201604    quality     9
#> 8  T02 201605    quality    10
#> 9  T01 201602 durability     9
#> 10 T01 201603 durability     9
#> 11 T01 201604 durability    10
#> 12 T01 201605 durability     9
#> 13 T02 201602 durability     9
#> 14 T02 201603 durability     8
#> 15 T02 201604 durability     8
#> 16 T02 201605 durability     9

这种格式正是ggplot2所喜爱的长格式数据,我们可以来画图:

代码语言:javascript
复制
library(ggplot2)

ggplot(toy_tests2, aes(x = ym, y = value)) + 
    geom_point() + 
    facet_grid(id ~ measure)

我们得到了按照产品id和measure分组,以ym为x轴,以value为y轴的散点图,可以清晰对比分组后两种产品质量差异(以年月)。

我们还可以用不同的颜色来表示产品,下图可以给出与上图相同的信息:

代码语言:javascript
复制
ggplot(toy_tests2, aes(x = ym, y = value, color = id)) + 
    geom_point() + facet_grid(. ~ measure)

通过sqldf包使用SQL查询数据框

有没有一种方法,能够直接使用SQL进行数据框查询,就像数据框是关系型数据库中的表一样呢?sqldf包给出肯定答案。该包吸收了SQLite轻量结构和易于嵌入R会话的优点,可以用下面代码安装:

代码语言:javascript
复制
install.packages("sqldf")

首先加载包:

代码语言:javascript
复制
library(sqldf)
#> 载入需要的程辑包:gsubfn
#> 载入需要的程辑包:proto
#> 载入需要的程辑包:RSQLite

注意加载sqldf包时,几个依赖包会自动加载进来。sql包的实现依赖这些包,它基本上是在R和SQLite之间传输数据和转换数据类型

读入前面使用的产品表格:

代码语言:javascript
复制
product_info = read_csv("../../R/dataset/product-info.csv")
#> Parsed with column specification:
#> cols(
#>   id = col_character(),
#>   name = col_character(),
#>   type = col_character(),
#>   class = col_character(),
#>   released = col_character()
#> )
product_stats = read_csv("../../R/dataset/product-stats.csv")
#> Parsed with column specification:
#> cols(
#>   id = col_character(),
#>   material = col_character(),
#>   size = col_integer(),
#>   weight = col_double()
#> )
product_tests = read_csv("../../R/dataset/product-tests.csv")
#> Parsed with column specification:
#> cols(
#>   id = col_character(),
#>   quality = col_integer(),
#>   durability = col_integer(),
#>   waterproof = col_character()
#> )
toy_tests = read_csv("../../R/dataset/product-toy-tests.csv")
#> Parsed with column specification:
#> cols(
#>   id = col_character(),
#>   date = col_integer(),
#>   sample = col_integer(),
#>   quality = col_integer(),
#>   durability = col_integer()
#> )

sqldf包的神奇之处在于我们可以使用SQL语句查询工作环境中的数据框,例如:

代码语言:javascript
复制
sqldf("select * from product_info")
#>    id      name  type   class released
#> 1 T01    SupCar   toy vehicle      yes
#> 2 T02  SupPlane   toy vehicle       no
#> 3 M01     JeepX model vehicle      yes
#> 4 M02 AircraftX model vehicle      yes
#> 5 M03    Runner model  people      yes
#> 6 M04    Dancer model  people       no

sqldf与SQLite一样,支持简单的选择性请求。

比如选择特定列:

代码语言:javascript
复制
sqldf("select id, name, class from product_info")
#>    id      name   class
#> 1 T01    SupCar vehicle
#> 2 T02  SupPlane vehicle
#> 3 M01     JeepX vehicle
#> 4 M02 AircraftX vehicle
#> 5 M03    Runner  people
#> 6 M04    Dancer  people

根据条件筛选记录:

代码语言:javascript
复制
sqldf("select id, name from product_info where released = 'yes' ")
#>    id      name
#> 1 T01    SupCar
#> 2 M01     JeepX
#> 3 M02 AircraftX
#> 4 M03    Runner

除了基本的数据库操作和分组统计,该包还支持查询多个数据框,比如:

代码语言:javascript
复制
sqldf("select * from product_info join product_stats using (id)")
#>    id      name  type   class released material size weight
#> 1 T01    SupCar   toy vehicle      yes    Metal  120   10.0
#> 2 T02  SupPlane   toy vehicle       no    Metal  350   45.0
#> 3 M01     JeepX model vehicle      yes Plastics   50     NA
#> 4 M02 AircraftX model vehicle      yes Plastics   85    3.0
#> 5 M03    Runner model  people      yes     Wood   15     NA
#> 6 M04    Dancer model  people       no     Wood   16    0.6

不过sqldf包的缺点也很明显:

  1. sqldf默认基于SQLite,因此SQLite的局限性就是该包的局限性,比如内置的分组汇总函数是有限的,而R本身的统计汇总函数要多得多
  2. 不方便动态编程
  3. SQL的限制性也限制了该包,我们难以像操作dplyr包一样用sqldf进行表格数据的操作、变换等等

如果你喜欢这个包并想用起来,阅读sqldf更多操作例子:https://github.com/ggrothendieck/sqldf#examples

学习自《R语言编程指南》,内心强烈推荐的一本书。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-01-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 优雅R 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 通过sqldf包使用SQL查询数据框
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档