Utilizing the grouping feature in the excellent R timevis package is well documented and examples are provided in the help page of timevis::timevis().
The documentation also says that it is possible to define subgroups, which
"Groups all items within a group per subgroup, and positions them on the same height instead of stacking them on top of each other."
I am having trouble understanding how to use this feature. For example, in the example below, I would expect that "event 1" and "event 2" are defined as their own subgroups and hence they would be positioned on the same height. However, this is not the case.
timedata <- data.frame(
id = 1:6,
start = Sys.Date() + c(1, - 10, 4, 20, -10, 10),
end = c(rep(as.Date(NA), 4), Sys.Date(), Sys.Date() + 20),
group = c(1,1,1,2,2,2),
content = c("event 1", "event 2", "event 2", "event 1", "range 1", "range 1"),
subgroup = c("1.1", "1.2", "1.2", "2.1", "2.2", "2.2")
)
groups <- data.frame(id = c(1,2), content = c("g1", "g2"))
timevis::timevis(data =timedata, groups = groups)
The result of the example code. The definition of subgroups is unsuccesful
How to correctly utilize the subgroups feature?
I'm working through the subgroup and subgroupOrder functions myself, and wanted to share a couple of tips. The code below should achieve overlaying the events on top of each other, as opposed to stacking them. Note the addition of stack = FALSE in the options list().
The other place to look is at the JS documentation: http://visjs.org/docs/timeline/
timedata <- data.frame(
id = 1:6,
start = Sys.Date() + c(1, - 10, 4, 20, -10, 10),
end = c(rep(as.Date(NA), 4), Sys.Date(), Sys.Date() + 20),
group = c(1,1,1,2,2,2),
content = c("event 1", "event 2", "event 2", "event 1", "range 1", "range 1"),
subgroup = c("1.1", "1.2", "1.2", "2.1", "2.2", "2.2")
)
groups <- data.frame(id = c(1,2), content = c("g1", "g2"))
timevis::timevis(data =timedata, groups = groups, options = list(stack = FALSE))
Produces this output,
Not sure if that's exactly what you're trying to achieve, but just a response. Hope you've made some progress otherwise!
Related
I am trying to create a shiny app that has multiple plots from different data frames. What I want is to have a selectinput for each plot where the user's selection changes the dataframe that is being plotted, with some other user inputs depending on the plot. When I do this, only one plot will render while the other plots need to have a value changed before they render. I have the following reprex to help explain what I mean.
library(shiny)
library(shinyBS)
library (dplyr)
library(wordcloud)
library(wordcloud2)
library(ggplot2)
library(plotly)
Survey1_Together <- read.csv(text = '"Answer", "Score"
"A", 20
"B", 10
"C", 14')
Survey1_user1 <- read.csv(text = '"Answer", "Score"
"A", 10
"B", 5
"C", 4')
Survey1_user2 <- read.csv(text = '"Answer", "Score"
"A", 10
"B", 5
"C", 4')
Survey2_Together <- read.csv(text = '"Answer", "Score"
"A", 200
"B", 120
"C", 140')
Survey2_user1 <- read.csv(text = '"Answer", "Score"
"A", 150
"B", 50
"C", 40')
Survey2_user2 <- read.csv(text = '"Answer", "Score"
"A", 150
"B", 70
"C", 100')
ui <- fluidPage(
fluidRow(column(width =4),titlePanel(h2("Wordcloud Survey 1", align = "center"))),
fluidRow(HTML("<br>")),
fluidRow(HTML("<br>")),
fluidRow(flowLayout((tags$div(selectizeInput("which", "Choose a user", choices = c("Together", "User 1", "User 2")), align = "center")),
(tags$div(sliderInput(inputId = "num", label = "Range of word usage", value = c(0,10000), min = 1, max = 10000), align = "center")), align = "center")),
fluidRow(HTML("<br style = 'line-height: 100px'>")),
fluidRow(column = 12, (tags$div(wordcloud2Output("wordcloud1", height = "600px"), align = "center")))
,
fluidRow(column(width =4),titlePanel(h2("Wordcloud survey 2", align = "center"))),
fluidRow(HTML("<br>")),
fluidRow(HTML("<br>")),
fluidRow(flowLayout((tags$div(selectizeInput("which2", "Choose a user", choices = c("Together", "User 1", "User 2")), align = "center")),
(tags$div(sliderInput(inputId = "num2", label = "Range of word usage", value = c(0,1000), min = 1, max = 1000), align = "center")), align = "center")),
fluidRow(HTML("<br style = 'line-height: 100px'>")),
fluidRow(column = 12, (tags$div(wordcloud2Output("wordcloud2"), align = "center"))),
fluidRow(HTML("<br style = 'line-height: 200px'>")),
)
server <- function(input, output, session) {
datasetInput1 <- reactive({
switch(input$which,
"Together" = Survey1_Together,
"User 1" = Survey1_user1,
"User 2" = Survey1_user2)})
wc1 <- reactive(
datasetInput1() %>%
filter(Score %in% (input$num[1]:input$num[2])))
output$wordcloud1 <- renderWordcloud2({wordcloud2(wc1(), color = "random-light", widgetsize = 10, size = 2)
})
datasetInput2 <- reactive({
switch(input$which2,
"Together" = Survey2_Together,
"User 1" = Survey2_user1,
"User 2" = Survey2_user2)})
wc2 <- reactive(datasetInput2() %>%
filter(Score %in% (input$num2[1]:input$num2[2])))
output$wordcloud2 <- renderWordcloud2({wordcloud2(wc2(), size = 1, fontFamily = "Arial", fontWeight = "bold", color = brewer.pal(8, "Set1"), minSize = .5, gridSize = 15, minRotation = 0.01, maxRotation = 180, rotateRatio = 1 )})
}
shinyApp(ui = ui, server = server)
Here, the first wordcloud will render while the second one needs to have a value changed before it can render. Does anyone know what I can do to make both plots render with the default value?
So far I have tried: Using unique values, using req functions (which I've seen in similar forums but it did not work here), and rearranging the code blocks. I apologize for any unnecessary libraries or if the slider range don't make sense, I pulled this code from a much larger project I am working on and I am using dummy variables here. The same problem happens in the larger project with the first plot rendering and all others needing a variable to change before rendering. Am I missing something as to how to make them all render? Thank you
With coding below I've been trying to be able to change y-axis for developing that graph, but I'm not quite sure what I'm doing worng. In this question it seems like they want to pull something alike but with a data table, difference is they have a Global dataframe, I need it to be reactive because I want the whole visualization to change when I change that input.
# GLOBAL #
# UI #
ui <- fluidPage(
# Set theme
theme = shinytheme("lumen"),
navbarPage("Analysis",
tabPanel("Impact",
titlePanel(
div(
h1(HTML(paste0("<b>","Graph against cluster count","</b>"))),
align = "left"
)
),
tags$br(),
fluidRow(
sidebarPanel(
hr(style="border-color: #606060;"),
h3(HTML(paste0("<b>","Clusters impact.","</b>"))),
h5("Key areas of patent concentration can be found around the clusters that reach higher levels."),
br(),
# Y axis selection
radioButtons("y_axis",
h4("What do you want to analyze IP collection against?"),
choices = list("Claims" = 3,
"Forward citations" = 4,
"Backward citations" = 5,
"Patent Strenght mean" = 6),
selected = 3), # radioButtons - y_axis
hr(style="border-color: #606060;"),
width = 3
),
mainPanel(
br(),
plotlyOutput("impact"),
br(),
width = 9
)
)
)
)
)
# SERVER #
server <- function(input, output, session) {
# Set maximun input size as 100Mb
options(shiny.maxRequestSize=100*1024^2)
# Plot
## Data setting
dtd5 <- reactive({
dtd5 <- structure(list(Topic = c("Topic 1", "Topic 3", "Topic 5", "Topic 9"),
Count = c(45L, 51L, 40L, 32L),
Claims = c(630, 346, 571, 599),
Forward = c(64, 32, 27, 141),
Backward = c(266, 177, 101, 397),
`Strength mean` = c(31, 25.22, 30.85, 39.59)),
row.names = c(NA, -4L), class = "data.frame")
dtd5 <- as.data.frame(dtd5)
})
## Visualization
output$impact <- renderPlotly({
# Color setting
ramp4 <- colorRamp(c("darkred", "snow3"))
ramp.list4 <- rgb( ramp4(seq(0, 1, length = 15)), max = 255)
# Scatterplot
y <- dtd5()[,input$y_axis]
p <- ggplot(dtd5(), aes(x=Count, y=y) ) +
geom_point(aes(col=Topic)) +
labs(y=colnames(dtd5())[input$y_axis],
x="Cluster count",
title="Cluster Impact") +
theme_minimal() +
scale_colour_manual(values=ramp.list4)
ggplotly(p) %>%
config(displayModeBar = FALSE)
})
}
shinyApp(ui,server)
In the console it prints this one out, so I'm sure structure works out fine but getting it inside the App is where something goes worng.
dtd5 <- structure(list(Topic = c("Topic 1", "Topic 3", "Topic 5", "Topic 9"
), Count = c(45L, 51L, 40L, 32L), Claims = c(630, 346, 571, 599
), Forward = c(64, 32, 27, 141), Backward = c(266, 177, 101,
397), `Stregth mean` = c(31, 25.22, 30.85, 39.59)), row.names = c(NA,
-4L), class = "data.frame")
# Scatterplot
y <- dtd5[,4]
p <- ggplot(dtd5, aes(x=Count, y=y) ) +
geom_point(aes(col=Topic)) +
labs(y=colnames(dtd5)[4],
x="Number of patents",
title="Cluster Impact") +
theme_minimal()
ggplotly(p) %>%
config(displayModeBar = FALSE)
In this other question they seem to be pulling it similarly to what I've made but it keeps on printing this error:
Listening on http://127.0.0.1:7465
Warning: Error in [.data.frame: undefined columns selected
[No stack trace available]
Sorry if it's too easy but
The problem appears to be with your radioButtons - even though the choices are set to return numeric values 3 through 6, it will return a string.
If you check help ?radioButtons you will see this noted under choices:
The values should be strings; other types (such as logicals and
numbers) will be coerced to strings.
If you specify as.numeric(input$y_axis) in both places in renderPlotly it should work.
i tried to create a marimekko chart in R Highcharter, following this example :
http://jsfiddle.net/highcharts/h2np93k1/
I cannot seem to get the sortIndex of the treemap to work, my code is as follows:
parentid <- c(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
sortIndex <- c(0, 1, 2, 3, 4, 0, 1, 2, 3, 4)
child <- c("Alpha", "Alpha", "Alpha", "Alpha", "Alpha", "Beta", "Beta", "Beta", "Beta", "Beta")
childid <- c(100, 100, 100, 100, 100, 200, 200, 200, 200, 200)
colorid <- c(100, 100, 100, 100, 100, 200, 200, 200, 200, 200)
parent <- c("Parent 1", "Parent 2", "Parent 3", "Parent 4", "Parent 5", "Parent 1", "Parent 2", "Parent 3", "Parent 4", "Parent 5")
value <- c(10, 60, 70, 20, 90, 50, 30, 10, 90, 10)
data <- data.frame(parentid, sortIndex, child, childid, colorid, parent, value)
hctreemap2(data, group_vars=c("parentid", "childid"),
size_var="value",
color_var="colorid",
layoutAlgorithm='stripes',
alternateStartingDirection = T,
stacking="percent",
levelIsConstant = F,
sortIndex=sortIndex,
levels = list(
list(level=1, dataLabels = list(enabled=T, align='left', verticalAlign='top'), borderWidth=3),
list(level=2, dataLabels = list(enabled=T))))
does anyone have any ideas?
I realize this question was several years ago, and Highcharter has changed since it was written.
This answer may not have worked in 2018, but it does work now.
At some point hctreemap and hctreemap2 were deprecated. The instructions from Highcharter are to use data_to_hierarchical to prepare the data and then use either hchart() or highchart() to create the treemap. However, this method will strip the sortIndex, so I don't think that's the route you would want to go.
Instead, I prepared the data by formatting it as it is in the JS link you provided and then graphed it.
The data:
# collect hc colors (like they did in the example)
colrs <- getOption("highcharter.color_palette")
# two data frames, one for each level
# id isn't as important until you go beyond 2 levels
pars <- data.frame(id = unique(data$parent),sortIndex = unique(data$sortIndex))
kids <- data.frame(
name = data$child, parent = data$parent, sortIndex = data$sortIndex,
value = data$value, color = data$color/100) %>% mutate(color = colrs[color])
# this assumes data is already sorted by sort order*
newData <- list() # for storing the data as hierarchical
invisible(map(1:nrow(pars),
function(j) {
p <- pars[j, ]$id # collect par id to find children
k <- kids[kids$parent == p, ] # isolate applicable children
pl <- list_parse(pars[j, ]) # make row a list
kl <- list_parse(k) # make each child row a list
newData <<- append(newData, pl) # add parent
newData <<- append(newData, kl) # add that parent's children
}))
Now the data is ready for plotting.
hchart(newData, type ="treemap", layoutAlgorithm = "stripes",
alternateStartingDirection = T)
I am working with the timevis library in R. I want a gannt diagram with one line per item. The following example will stack items after another if there is room. Is there a way to force the diagram to have as many rows as there are items?
library(timevis)
data <- data.frame(
id = 1:4,
content = c("Item one" , "Item two" ,"Ranged item", "Item four"),
start = c("2016-01-10", "2016-01-11", "2016-01-20", "2016-02-14"),
end = c(NA , NA, "2016-02-04", NA)
)
timevis(data)
This gives the following output from timevis:
But I want each of the items on a separate line
I am aware of other packages than timevis, but I would prefer using timvis as the interactivity is very usefull for what I am trying to vizualise.
From the examples, slightly modified:
timevis(data = data.frame(
start = c(Sys.Date(), Sys.Date()+1, Sys.Date() + 2, Sys.Date() + 3),
content = c("one", "two", "three", "four"),
group = c(1, 2, 3, 4)),
groups = data.frame(id = 1:4, content = c("G1", "G2", "G3", "G4"))
)
This should be a good starting point.
You need the option: stack = TRUE for this, this puts them on different lines inside a group, example final call below
tv <<- timevis(main,group, showZoom = FALSE,options = list(
editable = TRUE,stack = TRUE, showCurrentTime = FALSE,multiselect = TRUE,align = "center"))
I have what I know is going to be an impossibly easy question. I am showing an average number of days by month using a bar chart, using the following example:
dat <- structure(list(Days = c("217.00", "120.00", "180.00", "183.00",
"187.00", "192.00"), Amt = c("1,786.84", "1,996.53",
"1,943.23", "321.30", "2,957.03", "1,124.32"), Month = c(201309L,
201309L, 201309L, 201310L, 201309L, 201309L), Vendor = c("Comp A",
"Comp A", "Comp A", "Comp A", "Comp A",
"Comp A"), Type = c("Full", "Full",
"Self", "Self", "Self", "Self"
), ProjectName = c("Rpt 8",
"Rpt 8", "Rpt 8",
"Rpt 8", "Rpt 8",
"Rpt 8")), .Names = c("Days",
"Amt", "Month", "Vendor", "Type", "ProjectName"
), row.names = c("558", "561", "860", "1157", "1179", "1221"), class =
"data.frame")
ggplot(dat, aes(x=as.character(Month),y=as.numeric(Days),fill=Type))+
stat_summary(fun.y='mean', geom = 'bar')+
ggtitle('Rpt 8')+
xlab('Month')+
ylab('Average Days')+
geom_text(stat='bin',aes(y=100, label=paste('Avg:\n',..count..)))
Right now my labels are showing counts & showing up where ever i designate y.
I want to:
place labels at the top of the bars.
display the average, not the count.
I've pretty thoroughly - and unsuccessfully - tried most of the other solutions on SO & elsewhere.
Just got it:
means<-ddply(dat,.(Vendor,Type,Month), summarise, avg=mean(as.numeric(Days)))
ggplot(dat, aes(x=as.character(Month),y=as.numeric(Days),fill=Type))+
stat_summary(fun.y='mean', geom = 'bar')+
geom_text(data = means, stat='identity',
aes(y=avg+7, label=round(avg,0),group=Type))
i realize there is code nearly identical to this sitting elsewhere. my error came in placing the round's 0 outside the correct closing parenthesis -- thus moving all my labels to 0 on x axis... DUH!