Trying to use the sum operator in matplotlib gives an error - numpy

So I would like to mention first that I am completely new to basically everything that is linked to Jupyter Notebook, matplotlib and numpy stuff. So that's why I most likely will not be able to express my problem clearly. Therefore I am begging for your patience :) (ah yeah and my English sucks too so...)
Anyways, I am trying to create an interactive plot. Therefore, I want to display the function of the first n polynomes of the square wave where the value of n can be choosen by using a slider. This is what I got so far:
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['figure.figsize'] = (11,4)
plt.rcParams['figure.dpi'] = 150
from ipywidgets import interact,interactive, fixed, interact_manual
import ipywidgets as Widgets
def f(n):
plt.plot( np.arange(0,10), 1/pi * sum( 2/(i* pi) * (1- cos(i*pi) ) * sin(i*np.arange(0,10)) for i in range(1,n) ) )
plt.ylim(-2,2)
interact(f, n= 1)
Now, everything works fine until the line where I set my function, so the line with this
plt.plot(np.arange ...)
It gives me the following error:
ValueError: x and y must have same first dimension, but have shapes (10,) and (1,)
I already figured out that this has to do with the usage of the sum() Operator and using the variable n in it. If i don't put n in the sum, then everything works out nicely and I am getting my graph.
So, the question basically is what I will have to do to make my idea happen.
Thank you for your Responses, I know that my post might be very annoying to some of you because of its style or whatever and I am sorry for that.

Using the sum means you collapse the list of values down to a single value, that's what numpy is telling you - you have 10 x values and only 1 y value (because you just added them all up). I think what you are meaning to do is create a list of sums, so just move one closing parenthesis ()) from after the for i in range(n) to before it:
plt.plot(np.arange(0,10), 1/pi * sum(2/(i* pi) * (1- cos(i*pi)) * sin(i*np.arange(0,10))) for i in range(1,n))

So, for those of you who are interested in the answer (probably there are some): I found a nice and simple solution.
The Problem was the fact, that the line
interact(f, n= 1)
didn't work on its own. Now that I put it like this,
interact(f, n =widgets.IntSlider(min=2, max=100, step=1, value=2))
so by - most importantly - saying that the slider is supposed to be an IntSlider, everything works just fine!
Thank you for your help anyways! Since I am new on this platform, I don't know how solved questions can be closed, but this one here defenitely can be closed.

Related

change scientific notation abbreviation of y axis units to a string

First I would like to apologize as I know I am not asking this question correctly (which is why I cant find what is likely a simple answer).
I have a graph
As you can see above the y axis it says 1e11 meaning that the units are in 100 Billions. I would like to change the graph to read 100 Billion instead of 1e11.
I am not sure what such a notation is called.
To be clear I am not asking to change the whole y axis to number values like other questions I only want to change the top 1e11 to be more readable to those who are less mathematical.
ax.get_yaxis().get_major_formatter().set_scientific(False)
results in an undesired result
import numpy as np
from matplotlib.ticker import FuncFormatter
def billions(x, pos):
return '$%1.1fB' % (x*1e-9)
formatter = FuncFormatter(billions)
ax.yaxis.set_major_formatter(formatter)
located from https://matplotlib.org/examples/pylab_examples/custom_ticker1.html
produces

Better ticks and tick labels with log scale

I am trying to get better looking log-log plots and I almost got what I want except for a minor problem.
The reason my example throws off the standard settings is that the x values are confined within less than one decade and I want to use decimal, not scientific notation.
Allow me to illustrate with an example:
import matplotlib.pyplot as plt
%matplotlib inline
import matplotlib as mpl
import numpy as np
x = np.array([0.6,0.83,1.1,1.8,2])
y = np.array([1e-5,1e-4,1e-3,1e-2,0.1])
fig1,ax = plt.subplots()
ax.plot(x,y)
ax.set_xscale('log')
ax.set_yscale('log')
which produces:
There are two problems with the x axis:
The use of scientific notation, which in this case is counterproductive
The horrible "offset" at the lower right corner
After much reading, I added three lines of code:
ax.xaxis.set_major_formatter(mpl.ticker.ScalarFormatter())
ax.xaxis.set_minor_formatter(mpl.ticker.ScalarFormatter())
ax.ticklabel_format(style='plain',axis='x',useOffset=False)
This produces:
My understanding of this is that there are 5 minor ticks and 1 major one. It is much better, but still not perfect:
I would like some additional ticks between 1 and 2
Formatting of label at 1 is wrong. It should be "1.0"
So I inserted the following line before the formatter statement:
ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.2))
I finally get the ticks I want:
I now have 8 major and 2 minor ticks. Now, this almost looks right except for the fact that the tick labels at 0.6, 0.8 and 2.0 appear bolder than the others. What is the reason for this and how can I correct it?
The reason, some of the labels appear bold is that they are part of the major and minor ticklabels. If two texts perfectly overlap, they appear bolder due to the antialiasing.
You may decide to only use minor ticklabels and set the major ones with a NullLocator.
Since the locations of the ticklabels you wish to have is really specific there is no automatic locator that would provide them out of the box. For this special case it may be easiest to use a FixedLocator and specify the labels you wish to have as a list.
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import numpy as np
x = np.array([0.6,0.83,1.1,1.8,2])
y = np.array([1e-5,1e-4,1e-3,1e-2,0.1])
fig1,ax = plt.subplots(dpi=72, figsize=(6,4))
ax.plot(x,y)
ax.set_xscale('log')
ax.set_yscale('log')
locs = np.append( np.arange(0.1,1,0.1),np.arange(1,10,0.2))
ax.xaxis.set_minor_locator(ticker.FixedLocator(locs))
ax.xaxis.set_major_locator(ticker.NullLocator())
ax.xaxis.set_minor_formatter(ticker.ScalarFormatter())
plt.show()
For a more generic labeling, one could of course subclass a locator, but we would then need to know the logic to use to determine the ticklabels. (As I do not see a well defined logic for the desired ticks from the question, I feel it would be wasted effort to provide such a solution for now.)

Matplotlib namespace issues?

I have a question regarding the Matplotlib.pyplot and namespaces.
See the following code:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.pyplot import cm
x=np.linspace(0,1,28)
color=iter(cm.gist_rainbow_r(np.linspace(0,1,28)))
plt.clf()
for s in range(28):
c=next(color)
plt.plot(x,x*s, c=c)
plt.show()
The idea was to have the plots in different colors of the rainbow map.
Now what happens is that on first execution it works, but then things are getting weird.
On several consecutive executions the map is stopped being used and instead of that the default map is used.
I see that the problem may lie within the "c=c" in the plot function, but I have played around with different namings "c", "color", .... and could not find the systematic of the issue here.
Can someone reproduce the problem and (try the code at least 5 times or so consecutively) is able to explain, what is going on here?
Thanks
This is known issue with mpl + python3.4+ that has been fixed in mpl v1.5+.
Many of the style parameters have multiple aliases (ex 'c' vs 'color') which mpl was not merging properly and the artists were essentially getting told two different colors which internally means there is a dictionary with both 'c' and 'color' in it.
In python 3.4+ process-to-process order of iteration of dictionaries is random by default due to the seed for the underlying hash table being randomized (this was to prevent a possible DOS attack based on intentional hash table collisions). In older versions of python it so happened that the user supplied color always came later in the iteration order so things coincidentally worked.
The simple work around (iirc) is to use plot(x, y, color=c) or update to mpl 1.5.1.

how to shift x axis labesl on line plot?

I'm using pandas to work with a data set and am tring to use a simple line plot with error bars to show the end results. It's all working great except that the plot looks funny.
By default, it will put my 2 data groups at the far left and right of the plot, which obscures the error bar to the point that it's not useful (the error bars in this case are key to intpretation so I want them plainly visible).
Now, I fix that problem by setting xlim to open up some space on either end of the x axis so that the error bars are plainly visible, but then I have an offset from where the x labels are to where the actual x data is.
Here is a simplified example that shows the problem:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
df6 = pd.DataFrame( [-0.07,0.08] , index = ['A','B'])
df6.plot(kind='line', linewidth=2, yerr = [ [0.1,0.1],[0.1,0.1 ] ], elinewidth=2,ecolor='green')
plt.xlim(-0.2,1.2) # Make some room at ends to see error bars
plt.show()
I tried to include a plot (image) showing the problem but I cannot post images yet, having just joined up and do not have anough points yet to post images.
What I want to know is: How do I shift these labels over one tick to the right?
Thanks in advance.
Well, it turns out I found a solution, which I will jsut post here in case anyone else has this same issue in the future.
Basically, it all seems to work better in the case of a line plot if you just specify both the labels and the ticks in the same place at the same time. At least that was helpful for me. It sort of forces you to keep the length of those two lists the same, which seems to make the assignment between ticks and labels more well behaved (simple 1:1 in this case).
So I coudl fix my problem by including something like this:
plt.xticks([0, 1], ['A','B'] )
right after the xlim statement in code from original question. Now the A and B align perfectly with the place where the data is plotted, not offset from it.
Using above solution it works, but is less good-looking since now the x grid is very coarse (this is purely and aesthetic consideration). I could fix that by using a different xtick statement like:
plt.xticks([-0.2, 0, 0.2, 0.4, 0.6, 0.8, 1.0], ['','A','','','','','B',''])
This gives me nice looking grid and the data where I need it, but of course is very contrived-looking here. In the actual program I'd find a way to make that less clunky.
Hope that is of some help to fellow seekers....

matplotlib: working with range in x-axis

I'm trying to do a basic line graph here, but I can't seem to figure out how to adjust my x axis.
And here is the error I get when I try adjusting my range.
from pylab import *
plot ( range(0,11),[9,4,5,2,3,5,7,12,2,3],'.-',label='sample1' )
plot ( range(0,11),[12,5,33,2,4,5,3,3,22,10],'o-',label='sample2' )
xlabel('x axis')
ylabel('y axis')
title('my sample graphs')
legend(('sample1','sample2'))
savefig("sampleg.png",dpi=(640/8))
show()
File "C:\Python26\lib\site-packages\matplotlib\axes.py", line 228, in _xy_from_xy
raise ValueError("x and y must have same first dimension")
ValueError: x and y must have same first dimension
I want my range to be a list of strings: ["12/1/2007","12/1/2008", "12/1/2009","12/1/2010"]
Any suggestions?
Honestly, I found the code online and was trying to rewrite it to properly understand it. I think I'm going to start from scratch so that I know what I'm doing but I need help on where to start.
I posted another question which explains what I want to do here:
Using PyLab to create a 2D graph from two separate lists
range(0,11) should be range(0,10).
In addition to Steve's observation: If your points are always some y-value at the same consecutive integer x's, matplotlib makes the range even implicit.
plot([9,4,5,2,3,5,7,12,2,3],'.-',label='sample1')