• R|Shiny练习


    参考:https://docs.rstudio.com/shinyapps.io/

    1. 日期计算

    仿照:http://bjtime.cn/riqi/

    链接:https://dingdangsunny.shinyapps.io/DateCalculate/

    练习Shiny基本输入输出。

    library(shiny)
    ui <- fluidPage(
      titlePanel("使用Shiny进行日期计算"),
      h4(textOutput("currentTime")),
      helpText("请输入起止日期,计算日期间隔。"),
      helpText("默认计算当前日期与今年1月1日的间隔。"),
      dateRangeInput(inputId = "daterange", label = "日期范围:",
                     start = as.Date(paste(format(Sys.time()+8*60*60, 
                                                  "%Y"),
                                           "/01/01",sep = ""),
                                     "%Y/%m/%d"), 
                     end = as.Date(format(Sys.time()+8*60*60, 
                                          "%Y/%m/%d"),
                                   "%Y/%m/%d")),
      textOutput("datedif"),
      tags$hr(),
      helpText("请输入起始日期和日期间隔,推算目标日期。"),
      helpText("(输入负数则为向前推算。)"),
      dateInput(inputId = "date", label = "起始日期:"),
      numericInput(inputId = "days", label = "日期间隔:",
                   value = 100),
      textOutput("dateaft")
    )
    server <- function(input, output, session) {
      output$currentTime <- renderText({
        invalidateLater(1000, session)
        paste("当前时间是", Sys.time()+8*60*60)
      })
      output$datedif <- renderText({
        paste("相距", diff(input$daterange), "天")
      })
      output$dateaft <- renderText({
        d <- input$date + input$days
        paste("推算得日期为", d, format.Date(d,"%A"))
      })
    }
    shinyApp(ui = ui, server = server)

     这里时间加8小时调整一下时区。

    界面:

    APP链接:https://dingdangsunny.shinyapps.io/DateCalculate/

    2. FFT

    关于FFT(快速傅里叶变换):https://www.cnblogs.com/dingdangsunny/p/12573744.html

    链接:https://dingdangsunny.shinyapps.io/FastFourierTransform/

    2.1 源代码

    global.R

    library(dplyr)
    FFT<-function(data, Fs, isDetrend=TRUE)
    {
      # 快速傅里叶变换
      # data:波形数据
      # Fs:采样率
      # isDetrend:逻辑值,是否进行去均值处理,默认为true
      # 返回[Fre:频率,Amp:幅值,Ph:相位(弧度)]
      n=length(data)
      if(n%%2==1)
      {
        n=n-1
        data=data[1:n]
      }
      if(n<4)
      {
        result<-data.frame(Fre=0,Amp=0,Ph=0)
        return(result)
      }
      if(isDetrend)
      {
        data<-scale(data,center=T,scale=F)
      }
      library(stats)
      Y = fft(data)
      #频率
      Fre=(0:(n-1))*Fs/n
      Fre=Fre[1:(n/2)]
      #幅值
      Amp=Mod(Y[1:(n/2)])
      Amp[c(1,n/2)]=Amp[c(1,n/2)]/n
      Amp[2:(n/2-1)]=Amp[2:(n/2-1)]/(n/2)
      #相位
      Ph=Arg(Y[1:(n/2)])
      result<-data.frame(Fre=Fre,Amp=Amp,Ph=Ph)
      return(result)
    }
    SUB<-function(t,REG)
    {
      # 通过正则表达式提取输入数据
      m<-gregexpr(REG, t)
      start<-m[[1]]
      stop<-start+attr(m[[1]],"match.length")-1
      l<-length(start)
      r<-rep("1",l)
      for(i in 1:l)
      {
        r[i]<-substr(t,start[i],stop[i])
      }
      return(r)
    }
    #生成示例信号
    deg2rad<-function(a)
    {
      return(a*pi/180)
    }
    N = 256
    Fs = 150
    t = (0:(N-1))/Fs
    wave = (5 + 8*cos(2*pi*10.*t) + 
      4*cos(2*pi*20.*t + deg2rad(30)) + 
      2*cos(2*pi*30.*t + deg2rad(60)) + 
      1*cos(2*pi*40.*t + deg2rad(90)) + 
      rnorm(length(t))) %>%
      paste(collapse = ",")

    ui.R

    library(shiny)
    shinyUI(fluidPage(
      titlePanel("使用Shiny进行FFT分析"),
      sidebarLayout(
        sidebarPanel(
          selectInput(inputId = "input_mode",
                      label = "选择一种数据输入方式",
                      choices = c("文本输入", "上传文件")),
          textAreaInput(inputId = "data",
                    label = "原始数据:",
                    value = wave, 
                    rows = 10),
          fileInput("file", "选择CSV文件进行上传",
                    multiple = FALSE,
                    accept = c("text/csv",
                               "text/comma-separated-values,text/plain",
                               ".csv")),
          checkboxInput("header", "是否有表头", TRUE),
          radioButtons("sep", "分隔符",
                       choices = c("逗号" = ",",
                                   "分号" = ";",
                                   "制表符" = "	"),
                       selected = ","),
          numericInput(inputId = "Fs",
                       label = "采样频率:",
                       value = 150),
          sliderInput("xlim", "x坐标范围:",
                      min = 0, max = 1,
                      value = c(0,1)),
          sliderInput("ylim", "y坐标范围:",
                      min = 0, max = 1,
                      value = c(0,1)),
          checkboxInput("isDetrend", "数据中心化", TRUE),
          checkboxInput("showgrid", "添加网格线", TRUE)
        ),
        mainPanel(
          tabsetPanel(
            type = "tabs",
            tabPanel("图像", plotOutput(outputId = "data_in"),
                               plotOutput(outputId = "result")),
            tabPanel("频谱", 
                     helpText("频谱分析结果如下。"),
                     helpText("输入基频获取THD计算结果。"),
                     numericInput(inputId = "fund",
                                  label = "基频:",
                                  value = 10),
                     verbatimTextOutput("THD"),
                     numericInput(inputId = "num",
                                  label = "展示几行数据:",
                                  value = 15),
                     downloadButton("downloadData", "下载数据"),
                     tableOutput("resultview")
                     ),
            tabPanel("帮助",
                     helpText("这是一个基于Shiny创建的网页程序,
                              可以进行快速傅里叶变换(FFT)。",
                              "了解Shiny请访问:",
                              a(em("https://shiny.rstudio.com/"),
                                href="https://shiny.rstudio.com/")),
                     helpText("您可以选择在文本框中输入原始数据或通过CSV文件进行上传,
                              文本框中的数据应由逗号或空格分隔开,CSV中的数据应处于表格
                              的第一列。图像面板中向您展示了原始数据的序列和FFT变换后的结果,
                              通过x和y坐标范围的滑块,可以将分析结果的图形进行放大。
                              如果勾选了数据中心化的复选框,则将滤除直流成分,否则将保留。
                              在频谱面板中,可以查看FFT分析的数值结果并进行下载,通过输入基频,
                              可以获得总谐波失真(THD)计算结果。"),
                     helpText("源代码和演示示例请访问:",
                       a(em("叮叮当当sunny的博客"),
                         href="https://www.cnblogs.com/dingdangsunny/p/12586274.html#_label1"),
                              "")
            )
          )
        )
      )
    ))

    server.R

    library(shiny)
    library(dplyr)
    shinyServer(function(input, output) {
      data <- reactive({
        if(input$input_mode=="文本输入")
        {
          return(SUB(input$data,"[-0-9.]+") %>%
            as.numeric())
        }
        else if(input$input_mode=="上传文件")
        {
          req(input$file)
          data <- read.csv(input$file$datapath,
                            header = input$header,
                            sep = input$sep)
          return(data[,1])
        }
      })
      result <- reactive({
        FFT(data(), input$Fs, input$isDetrend)
      })
      output$data_in <- renderPlot({
        ylabel <- function()
        {
          if(input$input_mode=="上传文件" & input$header==TRUE)
            return((read.csv(input$file$datapath,
                            header = TRUE, sep = input$sep) %>%
                     names())[1])
          else
            return("value")
        }
        par(mai=c(1,1,0.5,0.5))
        plot((1:length(data()))/input$Fs, data(),
             type = "l", main = "The original data", 
             xlab = "time/s", ylab = ylabel())
        if(input$showgrid)
        {
          grid(col = "darkblue", lwd = 0.5)
        }
      })
      output$result <- renderPlot({
        Fre_max <- max(result()$Fre)
        Amp_max <- max(result()$Amp)
        x_ran <- (input$xlim*1.1-0.05)*Fre_max
        y_ran <- (input$ylim*1.1-0.05)*Amp_max
        par(mai=c(1,1,0.5,0.5))
        plot(result()$Fre, result()$Amp, type = "l",
             xlab = "Frequency/Hz", ylab = "Amplitude",
             main = "FFT analysis results",
             xlim = x_ran, ylim = y_ran)
        if(input$showgrid)
        {
          grid(col = "darkblue", lwd = 0.5)
        }
      })
      output$resultview <- renderTable({
        r <- cbind(result()[1:input$num,], 
                   result()[(1+input$num):(2*input$num),])
        names(r) <- rep(c("频率", "幅值", "相位"), 2)
        r
      })
      output$THD <- renderPrint({
        n <- floor(dim(result())[1]/input$fund)
        A <- rep(0, n)
        for(i in 1:n)
        {
          A[i] <- result()$Amp[which(abs(result()$Fre-i*input$fund)==
                                       min(abs(result()$Fre-i*input$fund)))]
        }
        THD <- sqrt(sum((A[2:n])^2)/(A[1])^2)
        cat("总谐波失真THD = ",THD*100,"%",sep = "")
      })
      output$downloadData <- downloadHandler(
        filename = function() {
          return("FFTresult.csv")
        },
        content = function(file) {
          write.csv(result(), file)
        }
      )
    })

    2.2 测试

    由默认数据集测试得到界面如下:

    频率数据界面:

    帮助文本界面:

    https://www.cnblogs.com/dingdangsunny/p/12573744.html#_label2中提到的数据进行文件上传测试。

    APP链接:https://dingdangsunny.shinyapps.io/FastFourierTransform/

    另外,发现了一个用Shiny写的有趣的小工具,http://qplot.cn/toolbox/,可以一试……

  • 相关阅读:
    C# 技能鉴定 第三单元 第四单元题目总结
    C# 技能鉴定 第三单元 test 3_5
    C# 技能鉴定 第三单元 Test3_4
    C# 技能鉴定 第三单元的题目
    班级通讯录修改与维护
    C# 技能鉴定
    Windows 编程入门,如何注册账号
    Windows 编程入门,了解开发UWP应用的准备工作
    logback-spring.xml
    springboot和mybatis 配置多数据源
  • 原文地址:https://www.cnblogs.com/dingdangsunny/p/12586274.html
Copyright © 2020-2023  润新知