Easy way to draw a few specific grid lines in bold? - altair

I have a scatter plot centered around an origin. I want to draw the origin grid lines (one horizontal line, one vertical) in bold to make it easier to see where the origin is.
I can make two separate rule charts, each with one line in them, and lay them under my scatter plot, but that's annoying. Is there an easier way?
extent = 1.0
scale = alt.Scale(domain=(-extent, extent))
base = alt.Chart(pd.DataFrame([[0, -extent, extent]])).mark_rule()
xaxis = base.encode(
alt.Y('0:Q', scale=scale),
alt.X('1:Q'),
alt.X2('2:Q'),
)
yaxis = base.encode(
alt.X('0:Q', scale=scale),
alt.Y('1:Q'),
alt.Y2('2:Q'),
)
xaxis + yaxis + scatter

domainWidth in the configure_axisX or configure_axisY sets the thickness of the 'axis line':
import altair as alt
from vega_datasets import data
source = data.cars()
alt.Chart(source).mark_circle(size=60, clip=False).transform_calculate(
x = alt.datum.Horsepower-100,
y = alt.datum.Miles_per_Gallon - 25
).encode(
x=alt.X('x:Q', axis=alt.Axis(offset=-150)),
y=alt.Y('y:Q', axis=alt.Axis(offset=-190)),
color='Origin',
).configure_axisX(
domainWidth =3
).configure_axisY(
domainWidth =3
)

Related

Is there a way to make a bubble plot in Altair which has circles that aren't filled?

I am trying to develop a new data visualization/graphic, and the bubble plot available here is very similar to what I am trying to make in shape:
https://altair-viz.github.io/gallery/table_bubble_plot_github.html
However, the graph I am trying to make involves some shaded bubbles and some filled in. Is there a way to edit this graph so that the bubble marks are not always filled?
Thank you!
You could use the fillOpacity encoding linked to a field in your data and then set the domain and range of its scale, so that only the values you want have a completely transparent fill:
import altair as alt
from vega_datasets import data
source = data.github.url
fill_threshold = 12
alt.Chart(source).mark_circle(
stroke='black'
).encode(
x='hours(time):O',
y='day(time):O',
size='sum(count):Q',
fillOpacity=alt.FillOpacity(
'sum(count):Q',
scale=alt.Scale(
domain=[fill_threshold, fill_threshold + 0.01],
range=[0 ,1]
)
)
)
You can use the fillOpacity and stroke mark properties to make the marks into circles with no fill. For example:
import altair as alt
from vega_datasets import data
source = data.github.url
alt.Chart(source).mark_circle(
fillOpacity=0,
stroke='black'
).encode(
x='hours(time):O',
y='day(time):O',
size='sum(count):Q',
)

Add custom markers to Gantt Chart in Plotly

I’m new to plotly and I’m creating a gantt chart using px.timeline. There are 3 categories of data in my dataset, a normal task with a start and end time, and two types of task where the start and end time are same. I want the normal task to be a rectangle (which is how it is being plot) and the other two tasks to have a hourglass marker and a triangle marker instead of a very thin line ?
This is how my data looks :
data = [dict(Task=’’, start=’’, end=’’, shape=’<rect, hour, tri>’)]
Sample Data :
df = [dict(Task="Job A", Start='2009-01-01', Finish='2009-01-01', shape='hourglass'),
dict(Task="Job B", Start='2009-03-05', Finish='2009-04-15', shape='rectangle'),
dict(Task="Job C", Start='2009-05-30', Finish='2009-05-30', shape='triangle')]
Code :
fig = px.timeline(data, x_start="Start", x_end="Finish", y="Task")
fig.update_yaxes(autorange="reversed", ticklabelposition="outside left")
fig.update_layout(showlegend=False, height=2000, width=1255, margin_pad=10)
fig.show()
Example:
Sample Plot in Excel
Is there any way I can achieve this ?
Thanks !
I solved this after some hours of searching.
Split the data into three each corresponding to 3 different shapes and then plot and combine.
Create 3 individual Plots :
rect = px.timeline(rect, x_start="Start", x_end="Finish", y="Task", color="color")
dia = px.scatter(dia, x="Start", y="Task", color="color", symbol_sequence=['diamond'])
coll = px.scatter(coll, x="Start", y="Task", color="color", symbol_sequence=['hourglass'])
Update traces for individual plots if needed :
rect.update_traces(marker=dict(line=dict(width=1, color='black')))
dia.update_traces(marker=dict(size=12, line=dict(width=2)))
coll.update_traces(marker=dict(size=12, line=dict(width=2)))
Set the timeline plot's axis:
rect.update_xaxes(tickformat="%H:%M:%S.%L", tickmode='linear', dtick='120000')
rect.update_yaxes(autorange='reversed')
rect.update_layout(title=title, showlegend=False, height=2800, width=2000)
Overlay all Plots:
new_fig = go.Figure(data=rect.data + dia.data + coll.data, layout=rect.layout)
new_fig.show()

Having both X and Y axes' Scales in Altair respond to a selection interval

I'm bringing this question from Altair's github. (https://github.com/altair-viz/altair/issues/2456) Is there a way to get the Scale on Y-axis in the bottom chart to respond to the selection brush? I'd like to be able to pan around the top chart with a selection and see the zoomed-in results in the bottom chart. If I uncomment the alt.Y, then both the X and Y axes show Years and it's messed up. Is there a way to pass just an X or Y value in the 'brush' maybe? Thank you very much!
brush = alt.selection_interval(init={'x':[1950, 1970], 'y':[1500000, 2500000]}, encodings=['x', 'y'])
base = alt.Chart().mark_line().encode(
x=alt.X('Year:Q', title=None),
y='Deaths:Q',
color='Entity:N'
)
alt.vconcat(
base.add_selection(brush).encode().properties(height=150, width=150),
base.encode(
alt.X('Year:Q', scale=alt.Scale(domain=brush)),
#alt.Y('Deaths:Q', scale=alt.Scale(domain=brush)) # (un)commenting this line makes it work/fail only along the x-axis
).properties(
height=500, width=500
),
data='https://vega.github.io/vega-datasets/data/disasters.csv'
)
Yes, see Open the Chart in the Vega Editor
It filters the data of the 2nd chart using a filter transform on the brush param.

Shared axis labels with independent scale

When facet/concat-ing charts, I would like the axis labels to be shared (so only 1 label per column/row, here: Horsepower), but the scale to be independent. Is this possible?
I thought a combination of resolve_axis and resolve_scale would be the way to go, as the title is a part of Axis, but I didn't get it to work.
I'm also wondering what resolve_axis actually does different than resolve_scale, anyone has an example?
base = alt.Chart(source).mark_circle().encode(
x=alt.X('Horsepower:Q',),
y=alt.Y('Miles_per_Gallon:Q'),
color='Origin:N',
row=alt.Row('Origin:N'),
).properties(
width=200, height=100
)
base.resolve_axis(
x='shared' # doesn't do anything obvious
).resolve_scale(
x='independent'
)
Open the Chart in the Vega Editor
I found a hacky way to do this, by misusing the facet header:
base = alt.Chart(source).mark_circle(size=60).encode(
x=alt.X('Horsepower:Q',),
y=alt.Y('Miles_per_Gallon:Q',
axis=alt.Axis(title=''),),
color='Origin:N',
column=alt.Column('Origin:N', header=alt.Header(title='Miles_per_Gallon')),
).properties(
width=200, height=200
).configure_header(
labelExpr="['Origin',datum.value]",
titleOrient='left'
)
display(base.resolve_scale(y='shared'))
display(base.resolve_scale(y='independent'))
I don't know of any way to do what you're hoping for (independent scales with only a single outer axis title) via scale and guide resolution.
As to your question of the difference between resolve_scale and resolve_axis, an example may help.
Here's a chart with independent y scale:
import altair as alt
from vega_datasets import data
source = data.cars()
base = alt.Chart(source).mark_circle().encode(
x=alt.X('Horsepower:Q',),
y=alt.Y('Miles_per_Gallon:Q'),
color='Origin:N',
column=alt.Column('Origin:N'),
).properties(
width=150, height=150
)
base.resolve_scale(
y='independent'
)
And here's one with independent y axis:
base.resolve_axis(
y='independent'
)
In both cases, each chart gets its own axis (because independent scales imply independent axes), but only with an independent scale do the axes scales differ from each other.

Plot points playing games when I try to size by a value count in bokeh

I'm trying to get the plot points in a scatter graph to size according to the frequency of values in a column of data. The data is coming from a questionnaire.
My questions are: What am I doing wrong, and what can I do to fix it?
I can push out a simple plot with x and y values coming from 2 columns of data. The X axis represents a level (1-100), and the Y axis represents a choice users can make for each level (1-4). For this plot I want to track how many people choose 1-4 on each level - so I need to capture that 1-4 has been selected, then indicate how many times.
Simple plot works fine, though those points have multiple occurrences.
Here's the code for that:
# Set up the graph
WT_Number = data.wt # This is the X axis
CFG_Number = data.cfg # This is the Y axis
wt_cfg_plot = figure(plot_width=1000, plot_height=400,
title="Control Form Groups chosen by WT unit")
# Set up the plot points, including the Hover Tool
cr = wt_cfg_plot.scatter(WT_Number, CFG_Number, size=7,
fill_color="blue",
line_color=None, alpha=0.7, hover_fill_color="firebrick",
hover_line_color=None, hover_alpha=1)
Problem: I then added a value count and set it as the size, to get the plot points to adjust according to the value frequency. But now it pumps out this chart and throws an error:
Plot points are reacting to the code, but now they're doing their own thing.
I added a variable for the value counts (cfg_freq), and used that as the size:
cfg_freq = data['cfg'].value_counts()*4
cr = wt_cfg_plot.scatter(WT_Number, CFG_Number, size=cfg_freq, fill_color="blue",
line_color=None, alpha=0.7, hover_fill_color="firebrick",
hover_line_color=None, hover_alpha=1)
Here's the the last part of the error being thrown:
File "/Applications/anaconda/lib/python3.5/site-packages/bokeh/core/properties.py", line 722, in setattr
(name, self.class.name, text, nice_join(matches)))
AttributeError: unexpected attribute 'size' to Chart, possible attributes are above, background_fill_alpha, background_fill_color, below, border_fill_alpha, border_fill_color, disabled, extra_x_ranges, extra_y_ranges, h_symmetry, height, hidpi, left, legend, lod_factor, lod_interval, lod_threshold, lod_timeout, logo, min_border, min_border_bottom, min_border_left, min_border_right, min_border_top, name, outline_line_alpha, outline_line_cap, outline_line_color, outline_line_dash, outline_line_dash_offset, outline_line_join, outline_line_width, plot_height, plot_width, renderers, responsive, right, tags, title, title_standoff, title_text_align, title_text_alpha, title_text_baseline, title_text_color, title_text_font, title_text_font_size, title_text_font_style, tool_events, toolbar_location, tools, v_symmetry, webgl, width, x_mapper_type, x_range, xgrid, xlabel, xscale, y_mapper_type, y_range, ygrid, ylabel or yscale

Resources