How to show labels on x axis for each element? - f#

I have sequence of tuples containing filename and number.
I want to draw column graph where on X axis I have filenames.
My problem is that now only 3 labels (filenames) are shown under X axis. That's probably because more can't fit on screen. Or maybe X axis interval is wrong?
How to make chart display all filenames? Maybe there is a way to rotate those labels 90 degrees counterclockwise to make room for more labels?

You should be able to use:
|> Chart.WithXAxis (LabelStyle = ChartTypes.LabelStyle(Angle = -45, Interval = 1.0))
The angle of -45 gives a nice slope and the interval of 1.0 means nothing is excluded.
Here's a proof of concept I knocked up in FSI:
#load "C:/Somewhere/packages/FSharp.Charting.0.90.7/FSharp.Charting.fsx"
open FSharp.Charting;;
let data =
[
("Foo.jpg", 12)
("Bar.jpg", 22)
("Another.doc", 8)
("OneMore.txt", 15)
("LastOne.txt", 17)
("ReallyLastOne.txt", 6)
("Foo.jpg", 12)
("Bar.jpg", 22)
("Another.doc", 8)
("OneMore.txt", 15)
("LastOne.txt", 17)
("ReallyLastOne.txt", 6)
];;
data
|> Chart.Line
|> Chart.WithXAxis (LabelStyle = ChartTypes.LabelStyle(Angle = -45, Interval = 1.0))
;;

Related

Draw a line chart based on user input

Please help me to draw a simple line chart in python turtle module based on user input. I am able to draw the x and y axis. The x-axis tick is equal to the number of data points. For example, if the user input is 5 then it will be 5 ticks labelled 1 to 5 and so on. However, the tick for y-axis has 6 ticks(fixed) labelled from 0 to 20, increment in 4(0,4,8..20).
I can't figure out the logic for plotting y values based on user input. For example, if the user types 15, it needs to go to the corresponding data point in y axis and put a dot in there. Similarly, if the user types 5 it needs to go the corresponding value in y axis as well plus connecting to the preceding data point(in this case connecting 15 from previous point to 5 in the current point) and so on based on user input. Also, my x and y labeling could be done it in a better way. Here is my code. Any help is much appreciated. Please look at the image description, I am aiming for similar results.
import turtle as t
import time
wn = t.Screen() # create a window for the turtle to draw on
wn.title("Turtle Demo") # the title to show at the top of the window
WINDOW_WIDTH = 500 # size constants for easy changing
WINDOW_HEIGHT = 500
wn.setup(WINDOW_WIDTH, WINDOW_HEIGHT, 200, 10) # specify window size (width, height)
user_input = t.numinput(title='Line graph', prompt='How many data points:')
x_max = user_input
# print(userInput)
# graph window
x_min = 0
y_min = 0
y_max = 5
# tick info
t_l = 0.1
x_t_space = 1
y_t_space = 1
wn.setworldcoordinates(x_min, y_min, x_max, y_max)
# Draw x-axis
t.tracer(10)
t.hideturtle()
t.up()
t.goto(x_min, 0)
t.down()
t.goto(user_input, 0.0)
t.up()
# Draw the y-axis
t.goto(0.0, y_min)
t.down()
t.goto(0.0, y_max)
t.up()
# Draw the x tick marks
n_x_ticks = int((x_max - x_min) / x_t_space) + 1
for tick in range(n_x_ticks):
loc = x_min + tick * x_t_space
t.up()
t.goto(loc, -t_l * 0.4)
t.down()
t.goto(loc, t_l * 0.4)
t.up()
t.write(tick)
# Draw the y tick marks
y_label = range(0, 21, 4)
n_y_ticks = int((y_max - y_min) / y_t_space) + 1
for tick in range(n_y_ticks):
loc = y_min + tick * y_t_space
t.up()
t.goto(-t_l * 0.4, loc)
t.down()
t.goto(t_l * 0.4, loc)
for i in y_label:
tick = i
print(tick)
t.write(tick, align="left", font=("Arial", 8, "normal"))
# get user input and plot the y value as long as user needed.
# the below code marks the value in the x-axis itself, that is not what I want.
#I want the value to get plotted outside the axis as in the normal line chart
t.backward
t.goto(0, 0)
t.tiltangle(45)
user_value = t.numinput(title='Line graph', prompt='Enter the first value:')
t.shape("square")
t.stamp()
t.forward(user_value)
user_value = t.numinput(title='Line graph', prompt='Enter the next value:')
t.shape("square")
t.stamp()
t.forward(user_value)
user_value = t.numinput(title='Line graph', prompt='Enter the next value:')
t.shape("square")
t.stamp()
t.forward(user_value)
Line chart
The input size is defined by the user and you want the same size of y-values.
Do the following:
for i in range (0, int(user_input)):
user_value = t.numinput(title='Line graph', prompt='Enter the value:')
t.shape("square")
t.stamp()
t.forward(user_value)
EDIT:
Just use matplotlib, it is very simple
import numpy as np
import matplotlib.pyplot as plt
user = int(input("Enter number of data: "))
x = np.arange(user)
y = []
for i in range (0, user):
value = int(input("Enter value: "))
y.append(value)
y = np.array(y)
plt.scatter(x, y)
plt.plot(x, y)
plt.show()
Input:
Enter number of data: 9
Enter value: 10
Enter value: 30
Enter value: 20
Enter value: 50
Enter value: 60
Enter value: 35
Enter value: 38
Enter value: 12
Enter value: 31
Output:
which is the same as the chart you provided.

How to avoid connecting all the points of a function graph with Plotly

In a program that revolves around maths, I find myself using Plotly.NET (F#) to display user-defined functions. This works quite well, but there are cases where a function has discontinuities or even chunks defined over certain regions. For example, for the function f(x) defined by 0 if x <= 0 and 10 elsewhere, the expected graph (I used Wolfram Alpha here) is:
With Plotly and the code below,
let fn x = if x <= 0.0 then 0.0 else 10.0
let xs = [ -10.0 .. 0.1 .. 10.0 ]
let ys = Seq.map fn xs
Chart.Line(xs, ys, UseDefaults = false)
|> Chart.withTitle #"$f(x)$"
|> Chart.savePNG("example")
I get this graph:
As you can see, Plotly connects two points that shouldn't be connected (and I don't blame it, that's how the lib works). I wonder then how to avoid this kind of behaviour, which often happens with piecewise defined functions.
If possible, I would like a solution that is general enough to be applied to all functions / graphs, as my program does not encode functions in advance, the user enters them. The research I've done doesn't lead me anywhere, unfortunately, and the documentation doesn't show an example for what I want.
PS: also, you may have noticed, Plotly doesn't display the LaTex in the exported image, according to my research this is a known issue with Python, but if you know how to solve this with the .NET version of the lib, I'm also interested!
I don't think there's any way for Plotly to know that the function is discontinuous. Note that the vertical portion of your chart isn't truly vertical, because x jumps from 0.0 to 0.1.
However, you can still achieve the effect you're looking for by creating a separate chart for each piece of the function, and then combining them:
let color = Color.fromString "Blue"
let xsA = [ -10.0 .. 0.0 ]
let ysA = xsA |> Seq.map (fun _ -> 0.0)
let chartA = Chart.Line(xsA, ysA, LineColor = color)
let xsB = [ 0.0 .. 10.0 ]
let ysB = xsB |> Seq.map (fun _ -> 10.0)
let chartB = Chart.Line(xsB, ysB, LineColor = color)
[ chartA; chartB ]
|> Chart.combine
|> Chart.withLegend false
|> Chart.show
Note that there are actually two distinct points for x = 0 in the combined chart, so it's technically not a function. (Perhaps there's some way to show that the top piece is open, while the bottom piece is closed in Plotly, but I don't know how.) Result is:

Rotate 3D Grid Lua

Hi!
I was wondering how I would go about to rotate a 3D grid 90 degrees, or rather a 2D grid one layer at a time.
Layer 1 example:
X O X X X X X O X X
X X X X X X X O X O
O O X O O ==90° Right==> X X X X X
X X X X X X X O X X
X X X X X X X O X X
It would be nice if this worked in both directions so I don't have to reiterate it three more times just to rotate it to the left.
Don’t restructure your data - that could be very costly, especially if the grid size is very large. Instead, use different iteration logic to traverse the grid. For example:
With the above data, keep it as shown on the left:
rows = {}
rows[1] = {“X”, “O”, “X”, “X”, “X”}
rows[2] = {“X”, “X”, “X”, “X”, “X”}
rows[3] = {“O”, “O”, “X”, “O”, “O”}
rows[4] = {“X”, “X”, “X”, “X”, “X”}
rows[5] = {“X”, “X”, “X”, “X”, “X”}
Iteration method 1 would be:
for i = 1, #rows do
for j = 1, #rows[i] do
— Do something with rows[i][j]
end
end
That would read the data like the grid on the left: across the rows, top to bottom.
Iteration method 2 would be:
for i = 1, #rows[1] do
for j = #rows, 1, -1 do
— Do something with rows[j][i]
end
end
That would read the data on the left as if it were the grid on the right.
Now, it you actually need to rearrange the data (because its getting written out to an image file, for example), then use the above nested loops to traverse the grids and write out the cell values with each iteration.
Also: if your grids are always size 5x5, then you can simplify the above code. You can hard-code the loops to go from 1 to 5 instead of using the # length operator.

F# Charting No Automatic Axis Range Setting?

It's not really an issue, more of a question. I am using FSharp.Charting to graph a few quick things. One thing I noticed is that the chart doesn't automatically set the axis limits for you. Say I have a list of numbers that has values between 100,000 and 200,000. The y-axis will still be based at 0. It doesn't scale to give you a good view of the data. You have to do this yourself. Or maybe there is a way, and I just haven't figured it out yet. Has anyone else ran into this issue? Any suggestions?
I have searched the FSharp charting code on GitHub and found nothing built in that can do automatic alignment of any axis. The best one can do is do it manually or write a function to look at all the values and then set them based on that.
Since you did not show in your question how to set it manually I will state it here for those that don't know how it is done.
To manually set the Y axis use WithYAxis
let xs1 = [ for x in (double)(-100.0) .. 1.0 .. 100.0 do yield x]
let ys1 = xs1 |> List.map (fun x -> x**4.00)
let values1 = List.zip xs1 ys1
Chart.Line(values1)
.WithXAxis(Min=(-30.0), Max=(30.0), MajorTickMark = ChartTypes.TickMark(Interval=10.0, IntervalOffset = 5.0, LineWidth = 2))
.WithYAxis(Min=(100000.0), Max=(200000.0), MajorTickMark = ChartTypes.TickMark(Interval=20000.0, IntervalOffset = 10000.0, LineWidth = 2))

combine time series plot by using R

I wanna combine three graphics on one graph. The data from inside of R which is " nottem ". Can someone help me to write code to put a seasonal mean and harmonic (cosine model) and its time series plots together by using different colors? I already wrote model code just don't know how to combine them together to compare.
Code :library(TSA)
nottem
month.=season(nottem)
model=lm(nottem~month.-1)
summary(nottem)
har.=harmonic(nottem,1)
model1=lm(nottem~har.)
summary(model1)
plot(nottem,type="l",ylab="Average monthly temperature at Nottingham castle")
points(y=nottem,x=time(nottem), pch=as.vector(season(nottem)))
Just put your time series inside a matrix:
x = cbind(serie1 = ts(cumsum(rnorm(100)), freq = 12, start = c(2013, 2)),
serie2 = ts(cumsum(rnorm(100)), freq = 12, start = c(2013, 2)))
plot(x)
Or configure the plot region:
par(mfrow = c(2, 1)) # 2 rows, 1 column
serie1 = ts(cumsum(rnorm(100)), freq = 12, start = c(2013, 2))
serie2 = ts(cumsum(rnorm(100)), freq = 12, start = c(2013, 2))
require(zoo)
plot(serie1)
lines(rollapply(serie1, width = 10, FUN = mean), col = 'red')
plot(serie2)
lines(rollapply(serie2, width = 10, FUN = mean), col = 'blue')
hope it helps.
PS.: zoo package is not needed in this example, you could use the filter function.
You can extract the seasonal mean with:
s.mean = tapply(serie, cycle(serie), mean)
# January, assuming serie is monthly data
print(s.mean[1])
This graph is pretty hard to read, because your three sets of values are so similar. Still, if you want to simply want to graph all of these on the sample plot, you can do it pretty easily by using the coefficients generated by your models.
Step 1: Plot the raw data. This comes from your original code.
plot(nottem,type="l",ylab="Average monthly temperature at Nottingham castle")
Step 2: Set up x-values for the mean and cosine plots.
x <- seq(1920, (1940 - 1/12), by=1/12)
Step 3: Plot the seasonal means by repeating the coefficients from the first model.
lines(x=x, y=rep(model$coefficients, 20), col="blue")
Step 4: Calculate the y-values for the cosine function using the coefficients from the second model, and then plot.
y <- model1$coefficients[2] * cos(2 * pi * x) + model1$coefficients[1]
lines(x=x, y=y, col="red")
ggplot variant: If you decide to switch to the popular 'ggplot2' package for your plot, you would do it like so:
x <- seq(1920, (1940 - 1/12), by=1/12)
y.seas.mean <- rep(model$coefficients, 20)
y.har.cos <- model1$coefficients[2] * cos(2 * pi * x) + model1$coefficients[1]
plot_Data <- melt(data.frame(x=x, temp=nottem, seas.mean=y.seas.mean, har.cos=y.har.cos), id="x")
ggplot(plot_Data, aes(x=x, y=value, col=variable)) + geom_line()

Resources