I made this gantt chart in R using diagrammer::mermaid (reproducible code below):
It is nice, but I would like to:
Increase font size (I suppose this will make each line wider, making the current very long rectangle slightly more "square". I am fine with that)
Make the t-aixis labels more standard. The weeks for some, months for others seem very strange. I want to be able to tell the months and years apart in a concise way)
How can I implement these changes?
I am an R user with no knowledge of node.js, css, etc. I managed to find code snippets on the internet to create this, but do not understand anything about the style_widget or how to change it.
devtools::install_github('rich-iannone/DiagrammeR')
library(DiagrammeR)
library(tidyverse) #just for the pipe operator
style_widget <- function(hw=NULL, style="", addl_selector="") {
stopifnot(!is.null(hw), inherits(hw, "htmlwidget"))
# use current id of htmlwidget if already specified
elementId <- hw$elementId
if(is.null(elementId)) {
# borrow htmlwidgets unique id creator
elementId <- sprintf(
'htmlwidget-%s',
htmlwidgets:::createWidgetId()
)
hw$elementId <- elementId
}
htmlwidgets::prependContent(
hw,
htmltools::tags$style(
sprintf(
"#%s %s {%s}",
elementId,
addl_selector,
style
)
)
)
}
flx_BmP <- mermaid("
gantt
dateFormat YYYY-MM-DD
section Common
Application (1230 plants) :done, first_1, 2018-05-15, 2018-07-30
Elegible (1003) :done, first_1, 2018-06-15, 45d
Plants accept (576) :done, first_1, 2018-08-01, 2d
Q0 - Baseline (576) :done, first_1, 2018-08-02, 15d
Lottery (576) :done, first_1, 2018-09-10, 2d
section ITT (288)
Treated (223 77%) :done, first_2, 2018-09-20, 2018-12-15
Q1 :done, first_3, 2018-12-16, 2019-01-05
Q2 : first_3, 2019-06-01, 2019-06-15
section Control (288)
Q1 :done, first_3, 2018-12-16, 2019-01-05
Q2 : first_3, 2019-06-01, 2019-06-15
Treated (263) : first_3, 2019-06-16, 2019-09-15
") %>%
style_widget("display:none", "line.today")
flx_BmP
For axis format (question 1.), maybe your search for this :
axisFormat %d/%m
Doc : https://mermaidjs.github.io/gantt.html
Example :
gantt
title Gantt
dateFormat DD-MM-YYYY
axisFormat %d/%m
section One
Task One : 07-05-2019, 7d
Task Two : 09-05-2019, 7d
I don't know for the font size.
Link to a demo with your code : https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjo...
Related
My DataFrame looks similar to this:
name
reached points
Jose Laderman
13
William Kane
13
I am currently displaying the aggregated count of students reached points of an assignment on an Altair bar chart within Streamlit like this:
brush = alt.selection(type='interval', encodings=['x'])
interactive_test = alt.Chart(df_display_all).mark_bar(opacity=1, width=5).encode(
x= alt.X('reached points', scale=alt.Scale(domain=[0, maxPoints])),
y=alt.Y('count()', type='quantitative', axis=alt.Axis(tickMinStep=1), title='student count'),
).properties(width=1200)
upper = interactive_test.encode(
alt.X('reached points', sort=alt.EncodingSortField(op='count', order='ascending'), scale=alt.Scale(domain=brush, domainMin=-0.5))
)
lower = interactive_test.properties(
height=60
).add_selection(brush)
concat_distribution_interactive = alt.vconcat(upper, lower)
Which produces this output and everything looks fine
The information I want my tooltip to show is a list of students that reached the specific amounts of reached points I'm hovering over. When adding something like:
tooltip='name'
the way my bar chart seems to display values has now been altered to this
When adding something like
tooltip='reached points'
The data seems to be displayed normally but without a tooltip that gives me the necessary information. Is it possible to display tooltip data that isn't used in my x or y axis but still part of the DataFrame I'm putting into the chart?
I try to adapt the Selection Detail Example from altair doc (https://altair-viz.github.io/gallery/select_detail.html#selection-detail-example).
I won't detailed my Dataframe structure which is identical with the one from the example (included variable names).
The native code is working well :
# Data is prepared, now make a chart
selector = alt.selection_single(empty='all', fields=['id'])
base = alt.Chart(data).properties(
width=250,
height=250
).add_selection(selector)
points = base.mark_point(filled=True, size=200,opacity=0.9).encode(
x=alt.X('mean(y)',title='Durée de perception',scale=alt.Scale(domain=(11, 23))),
y=alt.Y('mean(x)',title='Taux de marge (%PM)'),
color=alt.condition(selector, 'id:O', alt.value('lightgray')),
tooltip = ['mean(y)','mean(x)']
)
timeseries = base.mark_bar(opacity=1).encode(
x=alt.X('time', title='Items'),
y=alt.Y('value', scale=alt.Scale(domain=(-1, 1)),stack=None),
color=alt.Color('id:O',scale=alt.Scale(domain=domain, range=range_))
#, legend=None)
).transform_filter(
selector
)
points | timeseries
No problem at this stage even if it could be useful to hide all the bars on right chart when no selection is made on the right chart (don't know if it's possible ?)
After that I try to add text to the scatter plot adding this at the end of the code :
text = points.mark_text(dy=-5).encode(
x=alt.X('mean(y)',title='Durée de perception',scale=alt.Scale(domain=(11, 23))),
y=alt.Y('mean(x)',title='NBV (%CA)'),
text='id:O'
)
(points + text) | timeseries
which leads to the following error message :
Javascript Error: Duplicate signal name: "selector094_tuple"
This usually means there's a typo in your chart specification. See the javascript console for the full traceback.
If you have any idea on how to do, i would be grateful
Thanks
The issue is that you cannot add the same selection to two different layers, which you do implicitly by deriving text from points. Try this instead:
text = alt.Chart(data).mark_text(dy=-5).encode(
x=alt.X('mean(y)',title='Durée de perception',scale=alt.Scale(domain=(11, 23))),
y=alt.Y('mean(x)',title='NBV (%CA)'),
text='id:O'
)
(points + text) | timeseries
I have series of monthly inventory data since 2017.
I have a series of inventory_forecasts since Dec2018
I am trying to plot the inventory data on a monthly-seasonal basis, and then overlay the inventory_forecasts of Jan2019 through Dec2019.
The dataframe looks like:
The first way I tried to make the chart does show all the data I want, but I'm unable to control the color of the inventory_zj line. Its color seems to be dominated by the color=year(date):N of the alt.Chart I configured. It is ignoring the color='green' I pass to the mark_line()
base = alt.Chart(inv.loc['2000':].reset_index(), title=f"usa total inventory").mark_line().encode(
x='month',
y="inventory",
color="year(date):N"
)
#this ignores my 'green' color instruction, and marks it the same light blue 2019 color
joe = base.mark_line(color='green').encode(
alt.Y('inventory_zj', scale=alt.Scale(zero=False), )
)
base+joe
I tried to use a layering system, but it's not working at all -- I cannot get it to display the "joe" layer
base = alt.Chart(inv.loc['2000':].reset_index(), title=f"usa total inventory").encode(
x='month(date)'
)
doe = base.mark_line().encode(
alt.Y('inventory', scale=alt.Scale(zero=False), ),
color="year(date):N"
)
joe = base.mark_line(color="green").encode(
alt.Y('inventory_zj', scale=alt.Scale(zero=False), ),
)
#looks identical to the first example
alt.layer(
doe, joe
).resolve_scale(
y='shared'
).configure_axisLeft(labelColor='black').configure_axisRight(labelColor='green',titleColor='green')
#independent shows a second y-axis (which is different from the left y-axis) but no line
alt.layer(
doe, joe
).resolve_scale(
y='independent'
).configure_axisLeft(labelColor='black').configure_axisRight(labelColor='green',titleColor='green')
I feel like i must be trying to assemble this chart in a fundamentally wrong way. I should be able to share teh same left y-axis, have the historic data colored by its year, and have a unique color for the 2019-forecasted data. But I seem to be making a mess of it.
As mentioned in the Customizing Visualizations docs, there are multiple ways to specify things like line color, with a well-defined hierarchy: encodings override mark properties, which override top-level configurations.
In your chart, you write base.mark_point(color='green'), where base contains a color encoding which overrides the mark property. If you don't derive the layer from base (so that it does not have a color encoding), then the line will be green as you hoped. Something like this:
base = alt.Chart(inv.loc['2000':].reset_index(), title=f"usa total inventory")
inventory = base.mark_line().encode(
x='month',
y="inventory",
color="year(date):N"
)
joe = base.mark_line(color='green').encode(
x='month',
y=alt.Y('inventory_zj', scale=alt.Scale(zero=False))
)
inventory + joe
I have been trying to work with textplot in R and am unsure if my question is possible or not, I know that par() can't be used to place two textplots in one plot. I have been using a page and this code to try and figure things out.
My question is: Is it possible to have two textplots within the same plot?
For example, in the par(mfrow=c(1,1)) scenario below, plot 1 is a texplot of species length. Say I wanted to replicate that textplot twice in that plot. Is that possible?
based on this site:
http://svitsrv25.epfl.ch/R-doc/library/gplots/html/textplot.html
textplot(version)
data(iris)
par(mfrow=c(1,1))
info <- sapply( split(iris$Sepal.Length, iris$Species),
function(x) round(c(Mean=mean(x), SD=sd(x), N=gdata::nobs(x)),2) )
textplot( info, valign="top" )
title("Sepal Length by Species")
What I want to do is put a second textplot within that plot, underneath the original. For arguments sake, replicating that textplot twice in the plot.
Is this possible?
Thanks!
Maybe you've figured it out in the last four months but I thought I'd chip in an answer anyway.
The code provided is most of the way towards doing what you require already, you just have to provide some additional inputs to title() and/or par(). Namely specify that the title is to be above both of the plots by using title("your title", outer = TRUE) and you can further adjust the position of the title with an option in par(), use par(mfrow = c(2,1), oma = c(0,0,"top",0)). Hopefully this answers your question.
require('gplots')
data(iris)
info <- sapply(split(iris$Sepal.Length, iris$Species),
function(x) round(c(Mean = mean(x), SD = sd(x), N = gdata::nobs(x)),2))
## Replace top with a numerical value to control the position of the title with respect to the
## top of the page.
par(mfrow = c(2,1), oma = c(0,0, top ,0))
textplot(info, valign = "top")
textplot(info, valign = "top")
title("Sepal Length by Species", outer = TRUE)
I'm brand new to Gnuplot and want to be able to graph a huge amount of data that looks like this:
Description violFine state
"Red Light Violation" $75.00 MD
"No Stop/Park Handicap" $502.00 MD
"Red Light Violation" $75.00 MD
"No Stop/Park Handicap" $502.00 MD
"Red Light Violation" $75.00 MD
"Red Light Violation" $75.00 MD
"Red Light Violation" $75.00 VA
"All Other Stopping or Parking Violations" $32.00 MD
"Red Light Violation" $75.00 MD
"Red Light Violation" $75.00 MD
As you can see, the top line is the names of the columns and I have many duplicate string values in the "Description" column. What I want to do is add up all the "violFine" numbers per unique "Description" and plot it with the "Description" on the x-axis and the total of the "violFines" on the y-axis. I've made a graph to illustrate what I'm talking about accessible at this link: http://i.imgur.com/NtZsZCR.jpg
(Sorry, I would've made it available on this page if I had enough reputation points).
Any help with going about this would be awesome! Thanks!
This sort of data processing task isn't well suited for gnuplot. Luckily, gnuplot is happy to let you use other tools to process the data and then pipe the result in. Here, I would use python:
from collections import defaultdict
import csv
import sys
d = defaultdict(list)
with open(sys.argv[1]) as fin:
next(fin) #remove the first line which doesn't contain data
reader = csv.reader(fin,delimiter=' ',quotechar='"')
for row in reader:
d[row[0]].append(float(row[1][1:]))
for k,v in d.items():
print '"{0}"'.format(k),sum(v)
Now in gnuplot, you can plot this as:
plot '< python script.py datafilename' using (column(0)):2:xtic(1) with lines
You can also do it in gnuplot only without external tools.
define a function inList(), which determines if an item is already in the list
create a list of unique items
define a function to get the index (i.e. x-value) of an item in the unique list
sum up the second column (after removing $) for equal x-values via smooth freq
every ::1 is skipping the first (header) line
For gnuplot>=5.0.0 you could also use sum and word() for the function inList(), which, however doesn't work for gnuplot 4.x because word() will ignore matching double quotes, e.g. word('"abc def" ghi',2) will return ghi in gnuplot 5.x, but def" in gnuplot 4.x. Hence, for 4.x there is another approach using strstrt() and adding an index number which will also work for 5.x
Script: (works for gnuplot>=4.6.0, March 2012)
### sum up values depending on keyword
reset
FILE = "SO/SO15316764.dat"
# create list of unique elements
c = 0
uniq = ''
inList(list,s) = strstrt(list,'"'.s.'"')
stats FILE u (uniq=uniq.(inList(uniq,strcol(1)) ? '' : sprintf('"%s" %d ',strcol(1),c=c+1))) every ::1 nooutput
getIndex(list,s) = (_n=inList(list,s)) ? int(word(list[_n+2+strlen(s):],1)) : 0
set boxwidth 0.8
set style fill solid 0.4
set key noautotitle
set xrange[0.5:c+0.5]
plot FILE u (getIndex(uniq,strcol(1))):(real(strcol(2)[2:])):xtic(1) every ::1 smooth freq w boxes
### end of script
Result: