用R做一个灵活的时间序列数据可视化工具

数据可视化的烦恼

数据分析师经常需要看数据。通常而言,数据或存放在MySQL数据库,或存放在Hadoop集群,或存放在阿里云的ODPS上。分析师根据业务需求写SQL语句从数据平台上提取出需要的数据,随后就面临着本文要重点讨论的怎么对数据可视化的难题。

对于一个固定的需求,通常需要观察多组数据。普通一点的分析师,可能是拷贝出一组数据,贴到Excel里,绘个图看一下,然后拷贝下一组数据;高级一点的分析师,可能是用R写好一段代码,然后修改分组的变量取值重复运行代码来观察多组数据。我在工作中动辄需要观察一百组数据,上述两种方法仍然不够好用,最好的方法是我鼠标点击一百次,每点击一次产生一幅图。

更可恶的是,每来一个新需求,不论是Excel还是R都得根据新需求定制化一遍操作或一套代码。

于是某一天,我实在忍不了,就尝试做了一个工具,将SQL写完后的数据可视化工作给工程化了。

这个工具首先支持select查询语句,执行成功后会显示执行结果,同时提供一个设置面板,让用户选择数据分组字段、x轴字段、y轴字段,然后生成分组结果,每点击一个结果,生成该分组数据的图。目前该工具只支持时间序列数据,能够绘制点图和线图。

技术方案

Shiny:R的Web开发框架,让数据分析师能够将分析成果快速转化为交互式网页分享给别人。

它跟通常我们了解的其他框架不一样:其他框架一般都是前后端分离,后端提供json,前端根据json绘图绘表,需要若干个程序员协同开发完成。然而这种可视化的小工具往往是得不到研发资源的支持,只能本数据分析师一人操刀前后端全包。

当一个项目以数据计算和可视化为核心,只投入数据分析师一个人,要求快速实现效果,对执行效率和负载无要求,那么shiny无疑是一个非常诱人的方案。

代码

#########################

时间序列数据可视化工具

@author: shuiping.chen@alibaba-inc.com

@date: 2016-07-10

#########################

library(shiny)
library(shinyjs)
library(DT)
library(dplyr)
library(tidyr)
library(stringr)
library(ggplot2)
library(scales)
library(plotly)

run.sql ',
"select * from xxxx limit 1000;",
'')
)
)
),
fluidRow(
column(12,
actionButton(inputId="refresh_button", label="加载数据", icon=icon("submit")
)
)
)
),

shinyjs::hidden(
div(id="table",

第二部分:SQL命令执行结果显示

    hr(),    dataTableOutput(outputId="sql_tab"),    # 第三部分:可视化规则设置    hr(),    textOutput(outputId="tab_button_message"),    sidebarLayout(      div(id="table_tool",          sidebarPanel(            selectInput(inputId="group_fields", label="绘图分组字段", choices=NULL, selected=NULL, multiple=TRUE),            selectInput(inputId="x_field", label="设置x轴字段,必须是日期时间", choices=NULL, selected=NULL, multiple=FALSE),            selectInput(inputId="y_line_fields", label="设置y轴线图字段", choices=NULL, selected=NULL, multiple=TRUE),            selectInput(inputId="y_point_fields", label="设置y轴点图字段", choices=NULL, selected=NULL, multiple=TRUE),            selectInput(inputId="group_shape_field", label="设置点图形状字段", choices=NULL, selected=NULL, multiple=FALSE),            actionButton(inputId="tab_button", label="显示分组表格", icon=icon("submit")),            width=3          )      ),      div(id="group_content",          mainPanel(dataTableOutput(outputId="group_tab"),                    width=9          )      )    )    )

),

第四部分:可视化图形

shinyjs::hidden(
div(id = "plot",
hr(),
plotlyOutput(outputId="case_viewer", height="600px")
)
)
)

server %
select(one_of(input$group_fields)) %>%
distinct()
shinyjs::show(id="group_content", anim=TRUE)
return(res)
})

output$tab_buttonmessage %
unite
("new_var", input$group_fields, remove=FALSE) %>%
filter(new_var==filter_str)

  if(length(input$y_line_fields) > 0) {    target_plot_data$dt %      tidyr::gather(col_name, thresh, one_of(input$y_line_fields)) %>%      dplyr::mutate(thresh=as.numeric(thresh))    p  0) {    target_plot_data$dt %      tidyr::gather(col_name, thresh, one_of(input$y_point_fields)) %>%      dplyr::mutate(thresh=as.numeric(thresh))    if(input$group_shape_field != "无") {      point_df[, input$group_shape_field] <- as.factor(point_df[, input$group_shape_field])      p <- p + geom_point(data=point_df, aes_string(x="dt",y="thresh",color="col_name", shape=input$group_shape_field))    }    else{      p <- p + geom_point(data=point_df, aes(x=dt,y=thresh,color=col_name))    }  }  p <- p  ggplotly(p)})shinyjs::show("plot", anim = TRUE)

})
}

shinyApp(ui=ui, server=server)
:为了让用户明白工具的使用方法,代码采用shinyjs在适当的时机隐藏/显示对应的组件;在eventReactive事件驱动的计算中,需要保证至少一个依赖与该reactive的组件处于显示状态,否则无法触发计算,observeEvent不存在此问题。

关键字:r, shiny

版权声明

本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部