How to add control for single subplot in plotly? - controls

In plotly I use a figure that contains several subplot.
For the last subplot I want to be able to change the type with a dropdown menu.
However, the "restyle" action of the dropdown seems to be applied to the whole figure?
If I use the dropdown, the other subplots disapear:
=> How to add a plotly control for a specific subplot?
or
=> How to tell a control do only influence the properties of a specific subplot?
Read data
import pandas as pd
​
# read in volcano database data
df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/master/volcano_db.csv",
encoding="iso-8859-1",
)
​
# frequency of Country
freq = df
freq = freq.Country.value_counts().reset_index().rename(columns={"index": "x"})
​
# read in 3d volcano surface data
df_v = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/volcano.csv")
Initialize figure with subplots
from plotly.subplots import make_subplots
import plotly.graph_objects as go
fig = make_subplots(
rows=3,
cols=2,
column_widths=[0.6, 0.4],
row_heights=[0.4, 0.2, 0.4],
specs=[
[{"type": "scattergeo", "rowspan": 2}, {"type": "bar"}],
[None, None],
[None, {"type": "surface"}]
]
)
# Add scattergeo globe map of volcano locations
scatter_geo = go.Scattergeo(
lat=df["Latitude"],
lon=df["Longitude"],
mode="markers",
hoverinfo="text",
showlegend=False,
marker=dict(color="crimson", size=4, opacity=0.8)
)
fig.add_trace(
scatter_geo,
row=1,
col=1
)
# Add locations bar chart
bar = go.Bar(
x=freq["x"][0:10],
y=freq["Country"][0:10],
marker=dict(color="crimson"),
showlegend=False
)
fig.add_trace(
bar,
row=1,
col=2
)
# Add 3d surface of volcano
surface_3d = go.Surface(
z=df_v.values.tolist(),
showscale=False
)
fig.add_trace(
surface_3d,
row=3,
col=2
)
fig
Add controls
# Add dropdown
updatemenu = dict(
buttons=list([
dict(
args=["type", "surface"],
label="3D Surface",
method="restyle"
),
dict(
args=["type", "heatmap"],
label="Heatmap",
method="restyle"
)
]),
direction="down",
pad={"r": 10, "t": 10},
showactive=True,
x=1,
y=0.4
)
fig['layout'].update(
updatemenus=[{}, {}, {}, {}, {}, updatemenu]
)
#Add slider
steps = []
for i in range(10):
step = dict(
method="update",
args=[{"title": "Slider switched to step: " + str(i)}], # layout attribute
)
steps.append(step)
slider = dict(
active=10,
currentvalue={"prefix": "Frequency: "},
pad={"t": 50},
steps=steps
)
fig.update_layout(
sliders=[slider]
)
Additional styling
# Update geo subplot properties
fig.update_geos(
projection_type="orthographic",
landcolor="white",
oceancolor="MidnightBlue",
showocean=True,
lakecolor="LightBlue"
)
# Rotate x-axis labels
fig.update_xaxes(tickangle=45)
# Set theme, margin, and annotation in layout
fig.update_layout(
autosize=False,
width=800,
height=500,
template="plotly_dark",
margin=dict(r=10, t=25, b=40, l=60),
scene_camera_eye=dict(x=2, y=2, z=0.3),
annotations=[
dict(
text="Source: NOAA",
showarrow=False,
xref="paper",
yref="paper",
x=0,
y=0)
]
)
fig.show()

Unfortunately, this is not a complete answer. But hopefully, what I'm about to show you will help you on your way. You see, you can specify which subplot to edit by the traces contained in that subplot. You do so by adding an integer in args() like so:
buttons=list([
dict(
args=["type", "surface", [2]],
label="3D Surface",
method="restyle"
)
And [2] references the position of your trace in fig.data:
(Scattergeo({
'geo': 'geo',
'hoverinfo': 'text',
'lat': array([ 34.5 , -23.3 , 14.501, ..., 15.05 , 14.02 , 34.8 ]),
'lon': array([ 131.6 , -67.62 , -90.876, ..., 42.18 , 42.75 , -108. ]),
'marker': {'color': 'crimson', 'opacity': 0.8, 'size': 4},
'mode': 'markers',
'showlegend': False
}),
Bar({
'marker': {'color': 'crimson'},
'showlegend': False,
'x': array(['United States', 'Russia', 'Indonesia', 'Japan', 'Chile', 'Ethiopia',
'Papua New Guinea', 'Philippines', 'Mexico', 'Iceland'], dtype=object),
'xaxis': 'x',
'y': array([184, 169, 136, 111, 87, 57, 54, 49, 41, 38], dtype=int64),
'yaxis': 'y'
}),
Surface({
'scene': 'scene',
'showscale': False,
The problem is, that doing it this way in your case will trigger some very peculiar behavior: when the button is set to heatmap, the data becomes bart of the Bar figure:
And what's even stranger, is that it looks the way it should when you select 3D Surface again:
And I honestly have no idea what causes this. Take a look for yourself in the complete code snippet below and see what you can make of it. Maybe we'll be able to figure it out eventually...
Complete code:
from plotly.subplots import make_subplots
import plotly.graph_objects as go
import pandas as pd
# read in volcano database data
df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/master/volcano_db.csv",
encoding="iso-8859-1",
)
# frequency of Country
freq = df
freq = freq.Country.value_counts().reset_index().rename(columns={"index": "x"})
# read in 3d volcano surface data
df_v = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/volcano.csv")
df_v
fig = make_subplots(
rows=3,
cols=2,
column_widths=[0.6, 0.4],
row_heights=[0.4, 0.2, 0.4],
specs=[
[{"type": "scattergeo", "rowspan": 2}, {"type": "bar"}],
[None, None],
[None, {"type": "surface"}]
]
)
# Add scattergeo globe map of volcano locations
scatter_geo = go.Scattergeo(
lat=df["Latitude"],
lon=df["Longitude"],
mode="markers",
hoverinfo="text",
showlegend=False,
marker=dict(color="crimson", size=4, opacity=0.8)
)
fig.add_trace(
scatter_geo,
row=1,
col=1
)
# Add locations bar chart
bar = go.Bar(
x=freq["x"][0:10],
y=freq["Country"][0:10],
marker=dict(color="crimson"),
showlegend=False
)
fig.add_trace(
bar,
row=1,
col=2
)
# Add 3d surface of volcano
surface_3d = go.Surface(
z=df_v.values.tolist(),
showscale=False
)
fig.add_trace(
surface_3d,
row=3,
col=2
)
# Add dropdown
updatemenu = dict(
buttons=list([
dict(
args=["type", "surface", [2]],
label="3D Surface",
method="restyle"
),
dict(
args=["type", "heatmap", [2]],
label="Heatmap",
method="restyle"
)
]),
direction="down",
pad={"r": 10, "t": 10},
showactive=True,
x=1,
y=0.4
)
fig['layout'].update(
updatemenus=[{}, {}, {}, {}, {}, updatemenu]
)
#Add slider
steps = []
for i in range(10):
step = dict(
method="update",
args=[{"title": "Slider switched to step: " + str(i)}], # layout attribute
)
steps.append(step)
slider = dict(
active=10,
currentvalue={"prefix": "Frequency: "},
pad={"t": 50},
steps=steps
)
fig.update_layout(
sliders=[slider]
)
# Update geo subplot properties
fig.update_geos(
projection_type="orthographic",
landcolor="white",
oceancolor="MidnightBlue",
showocean=True,
lakecolor="LightBlue"
)
# Rotate x-axis labels
fig.update_xaxes(tickangle=45)
# Set theme, margin, and annotation in layout
fig.update_layout(
autosize=False,
width=800,
height=500,
template="plotly_dark",
margin=dict(r=10, t=25, b=40, l=60),
scene_camera_eye=dict(x=2, y=2, z=0.3),
annotations=[
dict(
text="Source: NOAA",
showarrow=False,
xref="paper",
yref="paper",
x=0,
y=0)
]
)
fig.show()

Related

how to use seaborn objects scale with two visualisations with same kwargs?

I'm trying to create bar plot with labels on bars. Position of labels and color of labels depends on column of dataframe. Also, I would like to color bars by column.
My data:
data = {
'Survived': ['0', '1'],
'count': [500, 100],
'label_position': ['R', 'L']
}
df = pd.DataFrame(data)
I tried to create following plot:
import seaborn.objects as so
p = (
so.Plot(df, x='count', y='Survived')
.add(so.Bar(alpha=1), color='Survived')
.add(
so.Text({"fontweight": "bold"}),
text='count',
halign='label_position',
color="label_position"
)
.scale(
halign={'L':'left', 'R':'right'},
color={'L':'black', 'R':'white'}
)
)
p.plot()
but this code raises following error:
PlotSpecError: Scale setup failed for the `color` variable. See the traceback above for more information.
because both visualizations have attribute color.
I'm able co color bars, or the text, but not both at once.
Colored bars:
color the bars
Colored text:
color the text
Is there any posibility to color both?
If we see the traceback above for more information as the exception message suggests, it says
ValueError: No entry in color dictionary for '0', '1'
So we could try adding entries for those keys:
(
so.Plot(df, x='count', y='Survived')
.add(so.Bar(alpha=1), color='Survived')
.add(
so.Text({"fontweight": "bold"}),
text='count',
halign='label_position',
color="label_position",
)
.scale(
halign={'L':'left', 'R':'right'},
color={'L':'black', 'R':'white', '0': 'black', '1': 'white'}, # <-----
)
)
That works but now we have some entries in the legend that we probably don't want. There's not in general a way to control what shows up in the legend independently of what actually gets mapped for Nominal scales, but for this particular plot the color encoding is redundant anyway so we don't actually need the legend:
(
so.Plot(df, x='count', y='Survived')
.add(so.Bar(alpha=1), color='Survived', legend=False) # <-----
.add(
so.Text({"fontweight": "bold"}),
text='count',
halign='label_position',
color="label_position",
)
.scale(
halign={'L':'left', 'R':'right'},
color={'L':'black', 'R':'white', '0': 'black', '1': 'white'},
)
)

Call Argument into other function Octave GNU?

I'm using Octave GNU for GUI Excel data.
I want to ask you guys how can I call defined argument in another function.
Here is my code.
%%First Function = pushbutton_Callback
function pushbutton_Callback(hObject, eventdata, handles)
fileName = uigetfile('*.xlsx')%%excel data import
handles.fileName=fileName;
guidata(hObject, handles)
endfunction
%%Second Function = popupmenuX_Callback
function popupmenuX_Callback(hObject, eventdata, handles)
fileName = fileName #pushbutton_Callback;
printf ("in popupmenuX_Callback, calling pushbutton_Callback\n");
%%To nested function to prevent (because in Octave nested function is not accepted), I used subfunction as alternative%%
handles.fileName=fileName; %% This argument fileName I want to bring from first function
[numbers, colNames]=xlsread(fileName); %%read columns of excel data in first function
set(hObject,'string',colNames);
endfunction
If I put my functions like this, always come these errors.
>> fileName = V8.xlsx
error: superclass calls can only occur in methods or constructors
error: called from
popupmenuX_Callback at line 61 column 10
So what I want to do is, I want to bring defined Argument "fileName" in first function (pushbutton_Callback) to second function (popupX_callback). But it can not be defined in second function.
I've heard that nested function in octave can be resolved with "foo", "foobar" or "ex_top", "ex_a" function. But I can't not resolve the problem with "ex_"function. Then should I have to use "foo", "foobar" function to call arguments into other function?
Best regards!
===========================================================================
I edited my questions with my full codes.
(Full codes below)
So what I want to do is, just like this video. But in Matlab like in video, it can be made with GUIDE or Application designer but in Octave there are no functions like that. So as a octave Beginner, it is hard for me to solve the problem.
%%Versuch
%% Diagramm zeichen
%%============================================================================
close all
clear h
graphics_toolkit qt
pkg load io
%%Uicontrols
%%Graph
h.ax = axes ("position", [0.3 0.25 0.6 0.5]);
%%Title
h.plot_title_label = uicontrol ("style", "text",
"units", "normalized",
"string", "Versuchsergebnis",
"horizontalalignment", "left",
"position", [0.03 0.9 0.25 0.08]);
%% Design for excel data import
h.print_pushbutton = uicontrol ("style", "pushbutton",
"units", "normalized",
"string", "Excel Datei mitbringen",
"callback", #pushbutton_Callback,
"position", [0.03 0.8 0.3 0.09]);
%% Drawing axis
h.popupmenuX = uicontrol("Style","popupmenu",
"units", "normalized",
"string","X Axis",...
"callback", #popupmenuX_Callback,
"Position",[0.7 0.04 0.2 0.05]);
h.popupmenuY = uicontrol("Style","popupmenu",
"units", "normalized",
"string","Y Axis",
"callback",#popupmenuY_Callback,
"Position",[0.03 0.5 0.2 0.05]);
%%=============================================================================
%% Functions
%%=============================================================================
%% 1. Excel Data import
function pushbutton_Callback(hObject, eventdata, handles)
fileName = uigetfile('*.xlsx')%%excel data import
handles.fileName = fileName;
guidata(hObject, handles)
endfunction
%% 2. X Axis Information from excel data import
function popupmenuX_Callback(hObject, eventdata, handles)
fileName = pushbutton_Callback(hObject, eventdata, handles)
%%This code fileName causes error, that 'handles' is not defined.%%
handles.fileName = fileName; %% This argument fileName I want to bring from first function
[numbers, colNames] = xlsread(fileName); %%read columns of excel data in first function
set(hObject,'string',colNames);
endfunction
%% 3. Y Axis Information from excel data import
function popupmenuY_Callback(hObject, eventdata, handles)
filename = pushbutton_Callback(hObject, eventdata, handles)
handles.fileName = fileName;
[numbers, colNames] = xlsread(fileName);
set(hObject,'string',colNames);
endfunction
%%%% Plot the graph
a = xlsread (fileName);
xColNum = get(popupmenuX_Callback,'value');
yColNum = get(popupmenuY_Callback,'value');
fileName = handles.fileName;
x = a(:,xColNum);
y = a(:,yColNum);
h.ax = plot(x,y);
Example of GUI which allows loading a .csv file, and populating two popupmenus based on the csv headers.
Example data.csv file:
Col1, Col2, Col3
1, 2, 3
2, 4, 8
3, 8, 9
Example myscript.m
pkg load io
% Create the Gui Window which will hold all controls and relevant data.
GuiWindow = figure()
% An 'axes' object for displaying plots in the Gui Window
axes ("position", [0.3 0.25 0.6 0.5], 'tag', 'plotarea' );
% Static text element used as a title
uicontrol ("style", "text", "units", "normalized", "string", "Fur Zoo Hair Geb knees.", "horizontalalignment", "left", "position", [0.03 0.9 0.3 0.08] );
% A button for importing (excel) data
uicontrol ("style", "pushbutton", "units", "normalized", "string", "CSV Dat Eye Meat Bringen", "callback", { #pushbutton_Callback, GuiWindow }, "position", [0.03 0.8 0.35 0.09], 'tag', 'button' );
% Popupmenus for selecting appropriate X and Y axis to display in plots
uicontrol("Style","popupmenu", "units", "normalized", "string","X Axis", "callback", { #popupmenuX_Callback, GuiWindow }, "Position",[0.7 0.04 0.2 0.05], 'tag', 'XAxisMenu' );
uicontrol("Style","popupmenu", "units", "normalized", "string","Y Axis", "callback", { #popupmenuY_Callback, GuiWindow }, "Position",[0.03 0.5 0.2 0.05], 'tag', 'YAxisMenu' );
%%=============================================================================
%% Functions (preferably placed in their own files!)
%%=============================================================================
function pushbutton_Callback(hObject, eventdata, GuiWindow)
% Read in data from file, graphically selected by user
fileName = uigetfile('*.csv');
CellCsv = csv2cell( fileName );
Header = CellCsv(1, :);
Data = CellCsv(2:end, :);
% Populate the menu items for the X and Y Axis from the csv header
XAxisMenu = findobj( 'tag', 'XAxisMenu' );
set( XAxisMenu, 'string', Header );
YAxisMenu = findobj( 'tag', 'YAxisMenu' );
set( YAxisMenu, 'string', Header );
% Also store headers and data as GuiWindow app data, in case we need them again later.
setappdata( GuiWindow, 'Header', Header );
setappdata( GuiWindow, 'Data' , Data );
% Plot a preliminary plot in the plot area
XData = [Data{:, 1}];
YData = [Data{:, 1}];
plot( XData, YData, 'bo-', 'tag', 'plotobject' );
endfunction
%% 2. X Axis Information from excel data import
function popupmenuX_Callback( hObject, eventdata, GuiWindow )
Axes = findobj( 'tag', 'plotarea' );
Selection = get( hObject, 'value' );
XData = [ getappdata( GuiWindow, 'Data' ){ :, Selection } ];
PlotObj = findobj( 'tag', 'plotobject' );
set( PlotObj, 'xdata', XData )
endfunction
%% 3. Y Axis Information from excel data import
function popupmenuY_Callback( hObject, eventdata, GuiWindow )
Axes = findobj( 'tag', 'plotarea' );
Selection = get( hObject, 'value' );
YData = [ getappdata( GuiWindow, 'Data' ){ :, Selection } ];
PlotObj = findobj( 'tag', 'plotobject' );
set( PlotObj, 'ydata', YData )
endfunction
This demonstrates two methods of accessing other graphical objects within callbacks. One is providing an object as an argument (e.g., GuiWindow), and the other is providing 'tags' that can be used to identify objects via the findobj function.
Note that I stored data in the GuiWindow object only, not to each individual graphical object (like buttons etc). Also, I preferred setappdata, because it allows to store multiple data under individual names (whereas guidata only stores a single object, although this can be a struct).
Above there is Tasos's answer (with csv file), I applied his answer to my code, which works with excel file. Because the code xlsread ignores the columns, users should have to care about that.
Thank you again Tasos!
pkg load io
% Create the Gui Window which will hold all controls and relevant data.
GuiWindow = figure()
% An 'axes' object for displaying plots in the Gui Window
axes ("position", [0.3 0.25 0.6 0.5], 'tag', 'plotarea' );
% Static text element used as a title
uicontrol ("style", "text", "units", "normalized", "string", "Versuchsergebnis",'ForegroundColor','w','BackgroundColor',[0 0.4470 0.7410],'Fontweight','bold', "horizontalalignment", "center", "position", [0.03 0.9 0.35 0.08] );
% A button for importing (excel) data
uicontrol ("style", "pushbutton", "units", "normalized", "string", "Datei(xlsx) mitbringen", "callback", { #pushbutton_Callback, GuiWindow }, "position", [0.03 0.8 0.35 0.09], 'tag', 'button' );
% Popupmenus for selecting appropriate X and Y axis to display in plots
uicontrol("Style","popupmenu", "units", "normalized", "string","X Axis", "callback", { #popupmenuX_Callback, GuiWindow }, "Position",[0.7 0.04 0.2 0.05], 'tag', 'XAxisMenu' );
uicontrol("Style","popupmenu", "units", "normalized", "string","Y Axis", "callback", { #popupmenuY_Callback, GuiWindow }, "Position",[0.03 0.5 0.2 0.05], 'tag', 'YAxisMenu' );
%%=============================================================================
%% Functions (preferably placed in their own files!)
%%=============================================================================
function pushbutton_Callback(hObject, eventdata, GuiWindow)
% Read in data from file, graphically selected by user
fileName = uigetfile('*.xlsx');
[num,txt,raw] = xlsread(fileName);
header = raw(1,:);
Data = xlsread(fileName);
% Show fileName
button = findobj('tag', 'button');
set( button, 'string', fileName)
% Populate the menu items for the X and Y Axis from the csv header
XAxisMenu = findobj( 'tag', 'XAxisMenu' );
set( XAxisMenu, 'string', header );
YAxisMenu = findobj( 'tag', 'YAxisMenu' );
set( YAxisMenu, 'string', header );
% Also store headers and data as GuiWindow app data, in case we need them again later.
setappdata( GuiWindow, 'header', header );
setappdata( GuiWindow, 'Data' , Data );
% Plot a preliminary plot in the plot area
XData = Data(:, 1);
YData = Data(:, 1);
plot( XData, YData, 'tag', 'plotobject' );
endfunction
%% 2. X Axis Information from excel data import
function popupmenuX_Callback( hObject, eventdata, GuiWindow )
Axes = findobj( 'tag', 'plotarea' );
Selection = get( hObject, 'value' );
XData = [ getappdata( GuiWindow, 'Data' )( :, Selection ) ];
PlotObj = findobj( 'tag', 'plotobject' );
set( PlotObj, 'xdata', XData )
endfunction
%% 3. Y Axis Information from excel data import
function popupmenuY_Callback( hObject, eventdata, GuiWindow )
Axes = findobj( 'tag', 'plotarea' );
Selection = get( hObject, 'value' );
YData = [ getappdata( GuiWindow, 'Data' )( :, Selection ) ];
PlotObj = findobj( 'tag', 'plotobject' );
set( PlotObj, 'ydata', YData )
endfunction
The line
fileName = fileName #pushbutton_Callback;
doesn't do what you think it does.
It's a bit complicated to explain the background, but basically in matlab, new-style classes created with the classdef keyword, which also allow inheritance, allow you to call a method of a 'parent' class (or "superclass") via the methodname#parentclassname(args) syntax. Octave has ported this system to octave too, for matlab compatibility. The error you get effectively says you're trying to call a superclass method, in a context where it doesn't make sense (which is true, since you're not inside a classdef block).
This explains why you get that error.
Now, in terms of what you're trying to do, I think you basically just want to call the pushbutton_Callback function from within your popupmenuX_Callback one, right? So just do that, with appropriate arguments, e.g.:
filename = pushbutton_Callback(hObject, eventdata, handles)
[numbers, colNames] = xlsread(fileName);
PS. I would recommend you always indent code inside functions. It looks clearer and helps catch bugs!

Recharts value at pointer to show in tooltip?

Is it possible in Recharts to show a Horizontal line at the Y location where the user has their mouse over and retrieve that Y value so we can display it on the Tooltip?
https://meridian.a2z.com/components/tooltip/?platform=react-web
I've been trying to do some research into how we could get the Y value on the graph where the mouse is hovering or clicked, but I'm having trouble seeing where we could even pull that out.
Any tips on attributes or components we could use to grab this data? Is it even something we have access to from the library?
To clarify, we're trying to get the value of the Y axis at where the user has their cursor over the graph.
So if the graph looks like this and the user has their mouse at the pink dot location, I would be trying to grab out the value of ~7000 - what the y value would be at that graph location
Edit:
Note about responsiveness:
If you want to make this responsive, just adjust the chartBounds based on the padding/margin you've applied to the chart component and you should be good to go.
If you're trying something more advanced and need the height and width to pass to the chart component for more calculations, the following article should help: https://www.pluralsight.com/tech-blog/getting-size-and-position-of-an-element-in-react/
NOTE: This is a bit of a hack and may not be a perfect solution but it should be enough to get you on the right track
You should be able to use the chartX and chartY fields from onMouseMove. Unfortunately, this is just the pixel value under the cursor but you should be able to translate it into the range you are using for your graph.
Here is an example put together using the SimpleLineChart example recharts has up. This should work if you just want to get the Y value under the user's cursor and can be extended to get the X value as well.
const {LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend} = Recharts;
const data = [
{name: 'Page A', uv: 4000, pv: 2400, amt: 2400},
{name: 'Page B', uv: 3000, pv: 1398, amt: 2210},
{name: 'Page C', uv: 2000, pv: 9800, amt: 2290},
{name: 'Page D', uv: 2780, pv: 3908, amt: 2000},
{name: 'Page E', uv: 1890, pv: 4800, amt: 2181},
{name: 'Page F', uv: 2390, pv: 3800, amt: 2500},
{name: 'Page G', uv: 3490, pv: 4300, amt: 2100},
];
//The pixel bounds for the LineChart, 0,0 is the top left corner
// these were found using the inspector built into the web browser
// these are in pixels but correspond to the values used in your graph
// so 246 is 0 Y on the graph and 5 is 10000 Y on the graph (according to your data)
const chartBoundsY = {min: 246, max: 5}
// The bounds we are using for the chart
const chartMinMaxY = {min: 0, max: 10000}
// Convert the pixel value from the cursor to the scale used in the chart
const remapRange = value => {
let fromAbs = value - chartBoundsY.min
let fromMaxAbs = chartBoundsY.max - chartBoundsY.min
let normal = fromAbs / fromMaxAbs
let toMaxAbs = chartMinMaxY.max - chartMinMaxY.min
let toAbs = toMaxAbs * normal
return Math.ceil(toAbs + chartMinMaxY.min)
}
const SimpleLineChart = React.createClass({
render () {
return (
<LineChart
width={600} height={300} data={data}
margin={{top: 5, right: 30, left: 20, bottom: 5}}
onMouseMove={props => {
// We get the values passed into the onMouseMove event
if(props.isTooltipActive) {
// If the tooltip is active then we display the Y value
// under the mouse using our custom mapping
console.log(remapRange(props.chartY))
}
}}
>
<XAxis dataKey="name"/>
<YAxis/>
<CartesianGrid strokeDasharray="3 3"/>
<Tooltip/>
<Legend />
<Line type="monotone" dataKey="pv" stroke="#8884d8" activeDot={{r: 8}}/>
<Line type="monotone" dataKey="uv" stroke="#82ca9d" />
</LineChart>
)
}
})
ReactDOM.render(
<SimpleLineChart />,
document.getElementById('container')
)
You can open this example in jsfiddle and paste in the code above in the JS editor to try it out for yourself. http://recharts.org/en-US/examples
Here is the documentation for the mouse event for the LineChart: http://recharts.org/en-US/api/LineChart
This can be done with the axis scale option together with d3's invert method.
The following code excerpt should give you an idea.
const domainY = d3.extent(data, d => d[keyY])
const scaleY = d3.scaleLinear().domain(domainY).range([0, 1])
<AreaChart
onMouseDown={(e) => console.log(scaleY.invert(e.chartY))}
...
<YAxis
domain={['auto', 'auto']}
dataKey={keyY}
type="number"
scale={scaleY}
...

KIVY Text within label

Trying to place text within a Rectangle. I even tried solution given here.
I want the text to be within Rectangle. This should holds good even if I change window size please. When I add_widget Actor I still want to continue pos_hint and size_hint format. Any idea please..
from kivy.uix.label import Label
from kivy.uix.relativelayout import RelativeLayout
from kivy.properties import ListProperty
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.scatter import Scatter
from kivy.core.window import Window
Window.clearcolor = (1, 1, 1, 1)
Window.size = (800, 600)
kv = '''
<Actor>:
canvas:
PushMatrix
Color:
rgba: 0,1,0,.8
Rectangle:
id: _rect_
size: self.width, self.height/12
pos: 0, 11 * (self.height / 12)
Line:
points: self.width/2, 11 * self.height/12, self.width/2, 0
width:2
PopMatrix
Label:
id: _actr_lbl
text: 'Hello World'
markup: True
color: 0,0,0,1
pos: 0, 11 * self.height/12
halign: 'center'
'''
Builder.load_string(kv)
class Actor(Scatter):
def __init__(self, **kwargs) :
super(Actor, self).__init__(**kwargs)
class TestApp(App):
def build(self):
layout = RelativeLayout()
layout.add_widget(Actor(pos_hint = {'center_x':0.5, 'top':0.95}, size_hint = (0.2, 1)))
return layout
if __name__ == '__main__':
TestApp().run()
I think you can accomplish what you want by adjusting your kv for the Label slightly:
Label:
id: _actr_lbl
text: 'Hello World'
markup: True
color: 0,0,0,1
size_hint: None, None
size: root.width, root.height/12
pos: 0, 11 * root.height/12
halign: 'center'
Adding size_hint: None, None allows the size to be effective. And referencing root for size and pos info keeps the Label sized and positioned correctly.

Ruby and Google Charts - using gchartrb

I'm having my first go at using Google charts using a Ruby wrapper called gchartrb. My first attempt was to draw a bar chart, which works fairly well, except that the largest value (Trend 2 - 800) hits the top of the y axis. I'm guessing this is a Google Charts issue, but I was wondering if there was a way around this problem so all values scale correctly?
labels = [1, 2, 3, 4]
GoogleChart::BarChart.new('800x200', "Bar Chart", :vertical, false) do |bc|
bc.axis :x, :labels => labels,
:color => '000000' # Months
bc.axis :y, :labels => [0, 100, 200, 300, 400, 500, 600, 700, 800, 900],
:color => '000000' # Number of books
bc.data "Trend 1", [100,200,300,400], '0000ff'
bc.data "Trend 2", [500,600,700,800], 'ff0000'
bc.width_spacing_options :bar_width => 50, :bar_spacing => 0, :group_spacing => 0
puts "\nBar Chart"
puts bc.to_url
end
Gave up on this gem and ended up using Google Charts directly.
for scaling issue, there is an option called 'range' for bc.axis attribute like,
bc.axis :y, :color => '000000', :range => [0,max_scale_value]
you can set max_scale_value to me maximum value of your data values.
1) If you are displaying bars side by side, you can set max_scale_value to 800, as per your data. i.e. max value from both of your arrays.
2) If you are displaying stacked bars(one above the other), then you should set max_scale_value to be maximum of [(100+500),(200+600),(300+700),(400+800)]
3) you need to remove labels property for y -axis,because it will automatically scale as per the values and give you labels.
thus, you wont have the scaling issue.
Hope it helps :)

Resources