python bokeh error with output_file in class - python-3.x

I have a probleme using bokeh in a class.
The following code is runing when i use the object "Graph" in the same file (.py), but not when i'm calling the class from an other file, and i don't know why.
class Graph():
import pandas as pd
from bokeh.models import HoverTool
from bokeh.plotting import figure, show, output_file, ColumnDataSource
def __init__(self, df, indicators=None):
self.df = df
self.output_file("test.html" , title='test')
....
I have the following error:
TypeError: output_file() got multiple values for argument 'title'
Does anybody know how can I fix it?
For information, the following code:
class Graph():
import pandas as pd
from bokeh.models import HoverTool
from bokeh.plotting import figure, show, output_file, ColumnDataSource
def __init__(self, df, indicators=None):
self.df = df
self.output_file("test.html")
....
returns:
Traceback (most recent call last):
File "Documents/Programmation/python/Trade/Indicators.py", line 50, in <module>
a = TradeGraph(df)
File "/Users/Alex/Documents/Programmation/python/Graph.py", line 29, in __init__
self.output_file("test.html")
File "/anaconda3/lib/python3.6/site-packages/bokeh/io/output.py", line 77, in output_file
root_dir=root_dir
File "/anaconda3/lib/python3.6/site-packages/bokeh/io/state.py", line 166, in output_file
if os.path.isfile(filename):
File "/anaconda3/lib/python3.6/genericpath.py", line 30, in isfile
st = os.stat(path)
TypeError: stat: path should be string, bytes, os.PathLike or integer, not Graph
and the following code:
class Graph():
import pandas as pd
from bokeh.models import HoverTool
from bokeh.plotting import figure, show, output_file, ColumnDataSource
def __init__(self, df, indicators=None):
self.df = df
self.output_file()
....
returns the same (last) error.
Thanks

You have evidently defined a method output_file on your own class, and that is where the problem is. (As an aside, please always try to ask questions with complete minimal code). Based on the output above, the most likely explanation is that you have forgotten to add the self parameter that Python methods should always have. That is, you have something like:
class Graph(object):
def output_file(title):
when you need something like:
class Graph(object):
def output_file(self, title):
However, I would question the value of having an output_file method at all. Unless you are doing something out of the ordinary, you should just call Bokeh's output_file function directly. However, please also note that output_file activates a persistent implicit mode. That is useful especially in interactive environments, but may not be in a program that saves lots of things. There is also a save function that just gives you explicit control wherever you want to perform a save.

Thank you for you answer,
I finnaly import each need module in each methode.
I thought i could all import them one time beteween the class definition and the class initialisation, but doesn't work,
Thanks

Related

Struggling to displaying the right (formatted) value for a matplotlib labels

Guide:
https://theoehrly.github.io/Fast-F1/examples_gallery/plot_qualifying_results.html#sphx-glr-examples-gallery-plot-qualifying-results-py
I am having trouble displaying the correct value or formatted form as a matplotlib label.
Issue: Bar Graph labels displaying as an unwanted, or badly formatted values.
(Is this TimeDelta[ns] in an integer under scientific notation? The dtype is timedelta64[ns])
Expected Values: The amount of time each driver is from the leader (s.ms) (HAM=0.038). Note: order is the same
print(times)
Code:
#!/usr/bin/python3-64
#required packages
#pip3 install fastf1
#pip3 install pandas
#pip3 install matplotlib
#pip3 install numpy
import matplotlib.pyplot as plt
import matplotlib.patches as pat
import fastf1 as ff1
import fastf1.plotting as ff1p
ff1p.setup_mpl(mpl_timedelta_support=True, color_scheme=None, misc_mpl_mods=False)
from fastf1.core import Laps
import pandas as pd
import numpy as np
from timple.timedelta import strftimedelta as td
import os
l=str.lower
def data_cache():
cache='/ff1_temp' #temp cache
while(True):
warn=input(l(f'!WARNING! A data cache will be made at {cache}\n'
f'Formula 1 Race Data will be downloaded to {cache}\n'
f'Would you like to continue? [y/n]\n'))
if(warn=='n'):
print('Quitting!\n')
exit(0)
elif(warn=='y'):
print(f'cache location: {cache}\n')
if not os.path.exists(cache): # os.path.exists(cache)
os.mkdir(cache) # os.mkdir(cache)
ff1.Cache.enable_cache(cache) # Fast F1 Cache API
break
else:
print('Plese Enter [y/n]\n')
continue
def data_load():
data=ff1.get_session(2021,'Netherlands','Q') #Y,L,S = Year, Location, Session
data.load(laps=True,telemetry=False,weather=False,messages=False)
return(data)
def data_graph():
data=data_load()
drivers=pd.unique(data.laps['DriverNumber'])
fll=list()
for row in drivers: #get fastest laps for session from each driver
fld=data.laps.pick_driver(row).pick_fastest()
fll.append(fld)
fl=Laps(fll).sort_values(by='LapTime').reset_index(drop=True)
flf=fl.pick_fastest()
fl['LapTimeDelta']=fl['LapTime']-flf['LapTime'] #determine the TimeDelta from leader
tc=list()
for index, lap in fl.iterlaps(): #team colours
color=ff1p.team_color(lap['Team'])
tc.append(color)
return(fl,tc,flf)
def data_plot():
fl,tc,flf=data_graph()
fig,ax=plt.subplots()
times=fl['LapTimeDelta']
fli=fl.index
# y x
bars=ax.barh(fli,times, color=tc,edgecolor='grey')
print(times) #expected values
ax.set_yticks(fl.index)
ax.set_yticklabels(fl['Driver'])
ax.set_xlabel('Time Difference (ms)')
#should be x axis?
ax.bar_label(bars) #(times)
ax.invert_yaxis()
lt=td(flf['LapTime'], '%m:%s.%ms')
plt.suptitle(f'2021 Dutch GP Qualifying\n'
f"Fastest at {lt} ({flf['Driver']})")
plt.show()
if(__name__=="__main__"):
data_cache()
data_plot()
exit(0)
results of print(bars)
results of print(type(times)) and print(type(bars))
What has been Attempted:
def data_plot():
ax.bar_label(times)
Traceback (most recent call last):
File "\python\datacollection\fp1.ff1.graph.py", line 144, in <module>
data_plot()
File "\python\datacollection\fp1.ff1.graph.py", line 132, in data_plot
ax.bar_label(times)
File "\Python\Python310\lib\site-packages\matplotlib\axes\_axes.py", line 2609, in bar_label
bars = container.patches
File "\Python\Python310\lib\site-packages\pandas\core\generic.py", line 5575, in __getattr__
return object.__getattribute__(self, name)
AttributeError: 'Lap' object has no attribute 'patches'
---
def data_plot_label(fli,times):
for i in range(len(fli)):
plt.text(i,times[i],times[i],ha='center',bbox=dict(alpha=0.8))
def data_plot():
data_plot_label(fli,times)
Close:
I'm still pretty green with this stuff,
Am I going about this correctly?
What are my options regarding labelling and matplotlib?
How do I set the correct formatted value for this label?
I find the graph is harder to understand without the actual values on it. It has less depth.
Relevant Docs:
https://theoehrly.github.io/Fast-F1/
https://pandas.pydata.org/docs/reference/index.html
https://matplotlib.org/stable/api/index
I overlooked something in the docs. I was not specifying the label only the container.
Reference:
https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.bar_label.html#matplotlib.axes.Axes.bar_label
Axes.bar_label(container, labels=None, *, fmt='%g', label_type='edge', padding=0, **kwargs)
Solution:
prfx='0 days 00:00:0'
sufx='000'
remov=''
def data_plot():
#removes leading and tailingzeros
times=times.astype(str).str.replace(prfx,remov).str.replace(sufx,remov)
#before: 0 days 00:00:0x.xxx000
#after: x.xxx
#over looked label, label_type=position-on-bar
ax.bar_label(bars, times, label_type='edge')
Just a little more formatting and it should look great!

Bokeh plot title 'str' object is not callable

In Jupyter Notebooks I read in a dataframe and create several plots with Pandas / Bokeh.
While creating one of the latter I get an error.
Search for similar problems said, that there might be somewhere above in the script something like
plt.title = "Title"
which overwrites the method. But this is not the case for me. I have nothing similar in the code above -exept in the figure parameters. Here the Bokeh documentation describes to set a figure title like I used it.
Using the part of the code that leads the the error in the complete notebook in a stand-alone script only does NOT lead to the error. So, also in my case the problem might have something to do with my code above. But maybe some of you has an idea when seeing this..(?)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from bokeh.plotting import figure, show, output_notebook, ColumnDataSource
from bokeh.io import output_notebook
from bokeh.layouts import column, gridplot
from bokeh.models import Label, Title
from bokeh.models import Div
data = df
output_notebook()
# Title of the overall plot
abovetitle = ("This should be the overall title of all graphs")
# GRAPH 1
s1 = figure(width = 250, plot_height = 250, title="Graph 1", x_axis_label = "axis title 1", y_axis_label = 'µs')
s1.line(x, y, width=1, color="black", alpha=1, source = data)
# s1.title.text = "Title With Options" # this is a instead-off 'title=' test, but does not solve the problem
# GRAPH 2
s2 = figure(width = 250, plot_height = 250, title="Graph 2", x_axis_label = "axis title 2, y_axis_label = 'µs')
s2.line(x, y, width=1, color="blue", alpha=1, source = data)
#s2.title.text = "Title With Options" # this is a instead-off 'title=' test, but does not solve the problem
# plot graphs:
p = gridplot([[s1, s2]])
show(column(Div(text=abovetitle), p))
leads to the type error
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-24-33e4828b986d> in <module>
31 # plot graphs:
32 p = gridplot([[s1, s2]])
---> 33 show(column(Div(text=title), p))
TypeError: 'str' object is not callable
Recalling
import matplotlib.pyplot as plt
does not solve the problem. Hence, recalling
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from bokeh.plotting import figure, show, output_notebook, ColumnDataSource
from bokeh.io import output_notebook
from bokeh.layouts import column, gridplot
from bokeh.models import Label, Title
from bokeh.models import Div
solves the problem. Any further idea what might cause this error?
In the mean time I got a very useful hint: In one of the prior cells I accidentially used a Bokeh API function name as variable name and overwrote the function. If someone faces a comparable problem have a look at your variable naming. Maybe there happend the same accident... ;-)
#############################
# Define column names of XData binary part
header = ["Col1","Col2","Col3"]
# Split XData in single, space separated columns
x_df = selected_df.XData.str.split(' ', expand=True)
x_df.drop(0, inplace=True, axis=1)
x_df.columns = header
#print(x_df)
# Binary XData to integer
for column in x_df: # DONT DO THAT!!!!! THIS OVERWRITES BOKEH API FUNCTION. EG. USE `col` INSTEAD OF `column`
x_df[column] = x_df[column].apply(int, base=16) # DONT DO THAT!!!!! THIS OVERWRITES BOKEH API FUNCTION. EG. USE `col` INSTEAD OF `column`

Python module not accessible to function inside class

Code below works as expected. It prints 5 random numbers.
import numpy as np
class test_class():
def __init__(self):
self.rand_nums = self.create_rand_num()
def create_rand_num(self):
numbers = np.random.rand(5)
return numbers
myclass = test_class()
myclass.rand_nums
However, the following does not work. NameError: name 'np' is not defined
import numpy as np
from test.calc import create_rand_num
class test_class():
def __init__(self):
self.rand_nums = create_rand_num()
myclass = test_class()
myclass.rand_nums
# contents of calc.py in test folder:
def create_rand_num():
print(np.random.rand(5))
But, this works:
from test.calc import create_rand_num
class test_class():
def __init__(self):
self.rand_nums = create_rand_num()
myclass = test_class()
myclass.rand_nums
# contents of calc.py in test folder:
import numpy as np
def create_rand_num():
print(np.random.rand(5))
Why must I have 'import numpy as np' inside calc.py? I already have this import before my class definition. I am sure I am misunderstanding something here, but I was trying to follow the general rule to have all the import statements at the top of the main code.
What I find confusing is that when I say "from test.calc import create_rand_num," how does Python know whether "import numpy as np" is included at the top of calc.py or not? It must know somehow, because when I include it, the code works, but when I leave it out, the code does not work.
EDIT: After reading the response from #DeepSpace, I want to ask the following:
Suppose I have the following file.py module with contents listed as shown:
import numpy as np
import pandas as pd
import x as y
def myfunc():
pass
So, if I have another file, file1.py, and in it, I say from file.py import myfunc, do I get access to np, pd, and y? This is exactly what seems to be happening in my third example above.
In my third example, notice that np is NOT defined anywhere in the main file, it is only defined in calc.py file, and I am not importing * from calc.py, I am only importing create_rand_num. Why do I not get the same NameError error?
Python is not like C. Importing a module does not copy-paste its source. It simply adds a reference to it to the locals() "namespace". import numpy as np in one file does not make it magically available in all other files.
You have to import numpy as np in every file you want to use np.
Perhaps a worthwhile reading: https://docs.python.org/3.7/reference/simple_stmts.html#the-import-statement

python cv2.imread return none on 6th image

I am trying to import and read all images in a folder. However, when I have more than 5 images, cv2.imread returns none for the 6th image. I have tried using different file names, different files, etc, but I can't get it to work.
import cv2
import numpy as np
import matplotlib.pyplot as plt
from tkinter import filedialog
import os
from mpl_toolkits.mplot3d import Axes3D
global scan_dir
scan_dir = filedialog.askdirectory()
print(scan_dir)
x=os.listdir(scan_dir)
img={}
print(x)
for i in range(0,len(x)):
print(i)
img[i] = cv2.imread(x[i], cv2.IMREAD_GRAYSCALE)
indices[i] = np.where(img[i]<100)
I get the following error...(None is the return of print(img[i] on 6th iteration of the loop)
None
Traceback (most recent call last):
File "C:\CodeRepository\US-3D\GettingCloser.py", line 55, in <module>
indices[i] = np.where(img[i]<100)
TypeError: '<' not supported between instances of 'NoneType' and 'int'
I have the same problem if I try this
global scan_dir
scan_dir = filedialog.askdirectory()
print(scan_dir)
x=os.listdir(scan_dir)
img = cv2.imread(x[5], cv2.IMREAD_GRAYSCALE)
It will return that img is None. This is true for anything beyond the 5th image.
Must be something wrong with the file. dicts are an unordered Data structure. Should not give error always on 5th iteration. However, I have made the changes which will not throw the error. But you need to debug that image
for i in range(0,len(x)):
print(i)
img[i] = cv2.imread(x[i], cv2.IMREAD_GRAYSCALE)
if img[i]:
indices[i] = np.where(img[i]<100)

how to solve the keyerror when I load a CSV file using pandas

I use pandas to load a csv file and want to print out data of row, here is original data
orginal data
I want to print out 'violence' data for make a bar chart, but it occuar a keyerror, here is my code
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
c_data=pd.read_csv('crime.csv')
print(c_data.head())
print (c_data['violence'])
and the error
error detail
error detail
I tried use capital VIOLENCE,print (c_data['VIOLENCE']),but also failed
error detail
error detail
can someone tell me how to work it out?
Try the following if your data is small:
with open('crime.csv', 'r') as my_file:
reader = csv.reader(my_file)
rows = list(reader)
print rows[3]
If your data is big, try this:
from itertools import islice
with open('crime.csv', 'r') as my_file:
reader = csv.reader(my_file)
print next(islice(reader, 3, 4))

Resources