【问题标题】:Visualzing SLA Performance可视化 SLA 性能
【发布时间】:2018-07-12 02:55:17
【问题描述】:

我每个月都会为我们的高层领导撰写一份报告 - 它显示了 I.T.表现。诸如事件解决、系统可用性等。我一直在寻找将我拥有的一些数据可视化的方法,并找到了一个漂亮的表示,如下所示:

我喜欢这种布局。我所有的报告都在 RMarkdown 中,并带有一些混合的 LaTex。我一直在考虑如何在 Rmarkdown 中复制这样的东西,或者甚至只是使用嵌入在我的 markdown 文件中的原始 LaTex ......我已经知道我可以使用 sparklines 包来获取迷你图,值和标题可以从数据。我唯一的旅行是整个事情。

我可以在 ggplot 中做这样的事情吗?或者也许使用格子......我不知道如何将所有这些放在一起。

一些基本信息 - 我的数据集是一个 R Dataframe。每行包含不同的系统或度量。将有一系列包含性能(计数和百分比)的列。我设想某种循环可以构建每个盒子,然后以某种方式将它们全部放在一个网格中。

如果需要,我可以提供一个示例数据集,但它们非常基础。字段/列类似于:名称、目标、Jan2018、Feb2018 等。如果我需要某些指标的计数和百分比,我可能每个月都有包含计数和百分比的列。

关于如何重现这个的任何想法?

样本数据

这是一个示例数据集。我希望迷你图是百分比,但我也有每月的小时数。显示的数字可以是 YTD 小时数和 YTD 百分比。抱歉,数据集太晚了——我不得不对其进行清理以删除机密信息。我添加了 CSV 和 RData 格式。再次感谢!

Data CSV File

Data RData File

【问题讨论】:

  • 至少给我们一些示例数据集,我相信“它们非常基础”适用于你自己而不适用于其他人。
  • 这当然可以用 R 来完成,但最好的方式取决于你的传播。更新频率(每月或每秒);数据如何到达 R;仪表板如何到达用户。是否需要任何交互,还是只需要静态图像?布局是预先知道的(例如,总是需要相同的 12 个图块)还是动态的?如果您只需要静态图像,我会在 R 中完成所有操作(没有 markdown 或 LaTeX,只是为了避免复杂化)。
  • 如果您需要有关可重复共享数据的指针,请参阅How to make a reproducible example in R。我们不需要您的所有数据,但需要足够大的样本来尝试方法并展示可能的解决方案。如果您共享的数据是可复制/可粘贴的,您将获得更多帮助 - 使用 dput() 对此有好处。
  • 我会在一天结束之前得到一个样本数据集并上传它。到目前为止,谢谢大家的帮助!!
  • 所有 - 如果有帮助,添加到数据的链接。每个系统都应该有自己的盒子,盒子上显示的数字应该是当前的 YTD % 和 YTD 计数。迷你图应该是每月的百分比。谢谢!

标签: r latex r-markdown


【解决方案1】:

这个问题有很多部分,我同意 cmets 的观点,即确切的解决方案会因很多细节而异。但是假设您正在寻找一种创建某种形式的静态仪表板的解决方案,您可以使用经过大量编辑的 ggplot 构建类似的东西。

我写了一个函数metricplot,它可以很容易地创建很多这些较小的图表。它有以下变量:

  • df:包含数据的数据框
  • x & y:用于 x 和 y 轴的列
  • title:情节的标题
  • 颜色:小部件的颜色

函数如下:

#' Make a small metric plot
#' 
#' 
metricplot <- function(df, x, y, title, colour){

  # Find the change in values
  start <- df[[y]][1]
  end <- df[[y]][length(df)]
  change <- scales::percent((end - start)/start)


  plot <- 
    ggplot(df) +
    annotate("rect", xmin = -Inf, xmax = Inf, ymax = max(df[[y]] - 1), 
             ymin = min(df[[y]]), fill = "white", alpha = 0.5) +
    geom_line(aes_string(x, y), colour = "white", size = 2) +
    labs(title = title,
         subtitle = paste0(end, " / ", change)) +
    theme(axis.line=element_blank(),
          axis.text.x=element_blank(),
          axis.text.y=element_blank(),
          axis.ticks=element_blank(),
          axis.title.x=element_blank(),
          axis.title.y=element_blank(),legend.position="none",
          panel.background=element_blank(),
          panel.border=element_blank(),
          panel.grid.major=element_blank(),
          panel.grid.minor=element_blank(),
          plot.background = element_rect(fill = colour),
          plot.title = element_text(size = 20, colour = "white", face = "plain"),
          plot.subtitle = element_text(size = 40, colour = "white", face = "bold")) 

  return(plot)

}

将此函数与示例数据集一起使用:

 set.seed(123)
df2 <- data.frame(x = 1:20,
                  y = c(9, rep(10, 17), 12, 14),
                  z = c(14, rep(10, 17), 12, 11))

library(ggplot2)
library(ggthemes)

grid.arrange(metricplot(df2, "x", "y", "Metric 1", "#fc8d59"),
             metricplot(df2, "x", "y", "Metric 1", "#91cf60"),
             metricplot(df2, "x", "z", "Something Else", "#999999"),
             metricplot(df2, "x", "z", "One More", "#fc8d59"), ncol=4)

显然,这对数据的格式做了一些假设,但希望它能让你朝着正确的方向前进 :)

【讨论】:

  • 这很漂亮。
  • 我看到我喜欢的另一件事是您即时计算百分比。这使得生成数据集变得更加容易,因此我不必在制作图表之前预先确定 %。好东西。我可以调整此代码以接受函数的第三个参数以包含 %,但是为什么你已经在函数内部完成了它。我喜欢这个......你可以看到我在上面发布的数据集的意思。我将尝试将此代码修改为我的数据,我将重新发布我最终得到的内容,以防万一有人感兴趣。再次感谢!
  • 如果您对如何以较低字体获取“/”后的第二个数字(如原始示例)有任何建议,请告诉我。否则,就目前而言,这似乎工作得很好。
  • 我不完全确定,但您应该避免将多个问题包含在一个帖子中。 “ggplot 文本中的多种字体大小”将是一个有效的单独问题
  • 我会针对多种尺寸的字幕发布不同的问题...谢谢!
【解决方案2】:

我已经在@mikey-harper 的回答中完成了下面示例代码的代码重写的第一部分。这会修改他的代码以使用我的数据集格式。仍然需要进行一些调整才能获得我想要的格式,但就目前而言,这是一个好的开始。只是想发布我的进度。

# Needed Libraries

library(Hmisc)
library(zoo)
library(lubridate)
library(ggplot2)
library(ggthemes)
library(grid)
library(gridExtra)

# Plot Function

metricplot <- function(data = criticalSystemAvailabilityFullDetail, row = 1) {

  # Since data is organized by row, I need to pull only the columns I need 
  # for the particular row (system) specificied. Then turn it into columns
  # since ggplot works best this way.
  ytdMonths <- as.data.frame(names(data)[4:((month(Sys.Date())-1)+3)])
  ytdValue <- t(as.data.frame(data[row,((month(Sys.Date()))+3):(ncol(data)-2)][1,]))
  ytdData <- cbind(ytdMonths, ytdValue)
  names(ytdData)[1] <- "Month"
  names(ytdData)[2] <- "Value"

  # Since I need red, yellow and green for my thresholds, I already have my 
  # target. My rules for this are basically, green until it exceeds 50%
  # of the target, then it turns yellow. Once it exceeds the Target, it turns
  # red. This function is called when the plot is made to determine the background
  # color.
  colour <- function (system = data[row,]) {
    if(data[row,ncol(data)] < as.numeric(strsplit(data[row,2], "%")[[1]][1]) ) {
      return("#fc5e58")
    } else if((data[row,ncol(data)] > as.numeric(strsplit(data[row,2], "%")[[1]][1])) == TRUE & (data[row,ncol(data)] < ((as.numeric(strsplit(data[row,2], "%")[[1]][1]) + 100.00) / 2)) == TRUE) {
      return("#ebc944")
    } else {
      return("#8BC34A")
    }
  }

  # Now for the plot. I have made some slight modifications to this. For example, in the white area that 
  # represents the high and low - I have used 100% for the max and the target for the low. I do this dynamically
  # by using the target from the row (system) I am currently plotting. I adjusted the line size down to 1, since 
  # the preivous value made the line a little too big. 
  plot <- 
    ggplot(ytdData) +
    annotate("rect", xmin = -Inf, xmax = Inf, ymax = 100.000, ymin = as.numeric(strsplit(data[row,2], "%")[[1]][1]), fill = "white", alpha = 0.6) + # Create the plot
    geom_line(aes(x = as.yearmon(Month), y = Value), colour = "white", size = 1) +
    labs(title = data[row,1], subtitle = paste0(data[row,ncol(data)], "% / ", data[row,(ncol(data)-1)], " hours")) + # Add title and subtitle
    theme(axis.line=element_blank(), # Remove X-axis title
          axis.text.x=element_blank(), # Remove X-Xais Text
          axis.text.y=element_blank(), # Remove Y-Axis Text - Comment this whole line out if you want a scale on the y-axis.
          axis.ticks=element_blank(), # Remove X-Axis
          axis.title.x=element_blank(), # Remove X-Axis Titlke
          axis.title.y=element_blank(),legend.position="none", # Remove legend and Y-axis title
          panel.background=element_blank(), # Remove bland gray background
          panel.border=element_blank(), # Remove border
          panel.grid.major=element_blank(), # Remove Grid
          panel.grid.minor=element_blank(), # Remove Grid
          plot.background = element_rect(fill = colour()), # Red, Green, Yellow
          plot.title = element_text(size = 10, colour = "white", face = "plain"), # Main Title
          plot.subtitle = element_text(size = 15, colour = "white", face = "bold"))

  return(plot) # Return the plot.
}



# Now we build the the grid by calling each row. Depending on the size of the canvas, 
# you might want to break up how many rows on the grid you do. In my case, this 
# is going on an A4 size peice of paper, so I will probably limit it to about 5-6 rows 
# in order to provide a readable page. Squeezing 5 columns in could get you more
# on a page, too. 

grid.arrange(metricplot2(data = criticalSystemAvailabilityFullDetail, row=1),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=2),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=3),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=4),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=5),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=5),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=7),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=8),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=9),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=10),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=11),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=12),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=13),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=14),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=15),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=16),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=17),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=18),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=19),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=20),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=21),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=22),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=23),
             metricplot2(data = criticalSystemAvailabilityFullDetail, row=24), ncol=4)

我唯一缺少的是如何使时间(字幕的第二部分)更小。我不知道我是否可以使用第三个字幕,但需要尝试一下。否则,我需要弄清楚如何在字幕中使用不同的大小。否则,这似乎工作得很好。

【讨论】:

    猜你喜欢
    • 2019-05-27
    • 2019-05-13
    • 2021-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-09
    • 2019-02-16
    • 1970-01-01
    相关资源
    最近更新 更多