How can I save histogram plot in python? - python-2.7

I have following code that generates a histogram. How can I save the histogram automatically using the code? I tried what we do for other plot types but that did not work for histogram.a is a 'numpy.ndarray'.
a = [-0.86906864 -0.72122614 -0.18074998 -0.57190212 -0.25689268 -1.
0.68713553 0.29597819 0.45022949 0.37550592 0.86906864 0.17437203
0.48704826 0.2235648 0.72122614 0.14387731 0.94194514 ]
fig = pl.hist(a,normed=0)
pl.title('Mean')
pl.xlabel("value")
pl.ylabel("Frequency")
pl.savefig("abc.png")

This works for me:
import matplotlib.pyplot as pl
import numpy as np
a = np.array([-0.86906864, -0.72122614, -0.18074998, -0.57190212, -0.25689268 ,-1. ,0.68713553 ,0.29597819, 0.45022949, 0.37550592, 0.86906864, 0.17437203, 0.48704826, 0.2235648, 0.72122614, 0.14387731, 0.94194514])
fig = pl.hist(a,normed=0)
pl.title('Mean')
pl.xlabel("value")
pl.ylabel("Frequency")
pl.savefig("abc.png")
a in the OP is not a numpy array and its format also needs to be modified (it needs commas, not spaces as delimiters). This program successfully saves the histogram in the working directory. If it still does not work, supply it with a full path to the location where you want to save it like this
pl.savefig("/Users/atru/abc.png")
The pl.show() statement should not be placed before savefig() as it creates a new figure which makes savefig() save a blank figure instead of the desired one as explained in this post.

Related

Python - AttributeError: 'DataFrame' object has no attribute

I have a CSV file with various columns and everything worked perfectly for the past few months until I updated the file and got new information and now the one column does not appear to be picked up by Python. I am using Python 2.7 and have made sure I have the latest version of pandas.
When I downloaded the csv file from Yahoo Finance, I opened it in Excel and made changes to the format of the columns in order to make it more readable as all information was in one cell. I used the "Text to Column" feature and split up the data based on where the commas were.
Then I made sure that in each column there were no white spaces in the beginning of the cell using the Trim function in excel and left-aligning the data.
I tried the following and still get the same or similiar:
After the df = pd.read_csv("KIO.csv") I tried to read whether I can read the first few columns by using df.head() - but still got the same error.
I tried renaming the problematic column as suggested in a similiar post using:
df = df.rename(columns={"Close": "Closing"}) - here I got the same error again. "print df.columns" also led to the same issue.
"df[1]" - gave a long error with "KeyError: 1" at the end - I can print the entire thing if it it will assist.
Adding the "skipinitialspace=True" - no difference.
I thought the problem might be within the actual csv file information so I deleted all the columns and made my own information and I still got the same error.
Below is a portion of my code as the total code is very long:
enter code here
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as pltdate
import datetime
import matplotlib.animation as animation
import numpy as np
df = pd.read_csv("KIO.csv", skipinitialspace=True)
#df.head()
#Close = df.columns[0]
#df= df.rename(columns={"Close": "Closing"})
df1 = pd.read_csv("USD-ZAR.csv")
kio_close = pd.DataFrame(df.Close)
exchange = pd.DataFrame(df1.Value)
dates = df["Date"]
dates1 = df1["Date"]
The above variables have been used throughout the remaining code though so if this issue can be solved here the remaining code will be right.
This is copy/paste of the error:
Blockquote
Traceback (most recent call last):
File "C:/Users/User/Documents/PycharmProjects/Trading_GUI/GUI_testing.py", line 33, in
kio_close = pd.DataFrame(df.Close)
File "C:\Python27\lib\site-packages\pandas\core\generic.py", line 4372, in getattr
return object.getattribute(self, name)
AttributeError: 'DataFrame' object has no attribute 'Close'
Thank you so much in advance.
#Rip_027 This is in regards to your last comment. I used to have the same issue whenever I open a csv file by simply double clicking the file icon. You need to launch Excel first, then get external data. Link below has more details,which will serve as a guideline. Hope this helps.
https://www.hesa.ac.uk/support/user-guides/import-csv

how to get formula result in excel using xlwings

What i want to do is 1)get a folmula result in excel and 2)update the values to the existing excel file. [ I created and wrote the folmula using "xlsxwriter". But when I tried openpyxl (or pandas) to retrieve the folmula result, it returns 0. I want to use "xlwings" to solve this problem, but no idea how to do it. can anyone help?
#openpyx
wb = openpyxl.load_workbook(filename=xlsx_name,data_only=True)
ws = wb.get_sheet_by_name("sheet1")
print "venn_value",(ws.cell('X2').value)
#pandas
fold_merge_data=pd.read_excel(xlsx_name,sheetname=1)
print fold_merge_data['Venn diagram'][:10]
Yes, xlwings can solve this problem for you because it uses pywin32 objects to interact with Excel, rather than just reading/writing xlsx or csv documents like openpyxl and pandas. This way, Excel actually executes the formula, and xlwings grabs the result.
In order to get the value you can do:
import xlwings as xw
sheet = xw.sheets.active # if the document is open
#otherwise use sheet = xw.Book(r'C:/path/to/file.xlsx').sheets['sheetname']
result = sheet['X2'].value
Also, note that you can set the formula using, for example
sheet['A1'].value = '=1+1' # or ='B1*2' if you want to reference other cells
import xlwings as xw
sheet = xw['Sheet1']
a2_formula = sheet.range('A2').formula
sheet.range('A2:A300').formula = a2_formula #it copys relative
You can use this method for copy formula or value

How would I format data in a PrettyTable?

I'm getting the text from the title and href attributes from the HTML. The code runs fine and I'm able to import it all into a PrettyTable fine. The problem that I face now is that there are some titles that I believe are too large for one of the boxes in the table and thus distort the entire PrettyTable made. I've tried adjusting the hrules, vrules, and padding_width and have not found a resolution.
from bs4 import BeautifulSoup
from prettytable import PrettyTable
import urllib
r = urllib.urlopen('http://www.genome.jp/kegg-bin/show_pathway?map=hsa05215&show_description=show').read()
soup = BeautifulSoup((r), "lxml")
links = [area['href'] for area in soup.find_all('area', href=True)]
titles = [area['title'] for area in soup.find_all('area', title=True)]
k = PrettyTable()
k.field_names = ["ID", "Active Compound", "Link"]
c = 1
for i in range(len(titles)):
k.add_row([c, titles[i], links[i]])
c += 1
print(k)
How I would like the entire table to display as:
print (k.get_string(start=0, end=25))
If PrettyTable can't do it. Are there any other recommended modules that could accomplish this?
This was not a formatting error, but rather the overall size of the table created was so large that the python window could not accommodate all the values on the screen.
This proven by changing to a much smaller font size. If it helps anyone exporting as .csv then arranging in Excel helped.

networkx graph display using matplotlib- missing labels

I am writing a program which generates satisfiable models (connected graphs) for a specific input string. The details here are not important but the main problem is that each node has a label and such label can be lengthy one. So, what happens is that it does not fit into the figure which results in displaying all the nodes but some labels are partly displayed... Also, the figure that is displayed does not provide an option to zoom out so it is impossible to capture entire graph with full labels on one figure.
Can someone help me out and perhaps suggest a solution?
for i in range(0,len(Graphs)):
graph = Graphs[i]
custom_labels={}
node_colours=['y']
for node in graph.nodes():
custom_labels[node] = graph.node[node]
node_colours.append('c')
#nx.circular_layout(Graphs[i])
nx.draw(Graphs[i], nx.circular_layout(Graphs[i]), node_size=1500, with_labels=True, labels = custom_labels, node_color=node_colours)
#show with custom labels
fig_name = "graph" + str(i) + ".png"
#plt.savefig(fig_name)
plt.show()
Update picture added:
You could scale the figure
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()
G.add_edge('a'*50,'b'*50)
nx.draw(G,with_labels=True)
plt.savefig('before.png')
l,r = plt.xlim()
print(l,r)
plt.xlim(l-2,r+2)
plt.savefig('after.png')
before
after
You could reduce the font size, using the font_size parameter:
nx.draw(Graphs[i], nx.circular_layout(Graphs[i]), ... , font_size=6)

concatenate two images from plt.imsave with different cmaps without installing another package

I'm making movies by saving a series of images, then using ImageJ to put them together, as so:
for i in range(n):
fname = 'out_' + str(1000+i)
plt.imsave(fname, A[i], cmap=cmapA)
I'd like to somehow "concatenate" two images (so they appear side-by-side for example) and save, produced with different colormaps. So hypothetically:
for i in range(n):
fname = 'out_' + str(1000+i)
plt.hypothetical_imsave(fname, (A[i], B[i]), cmap=(cmapA, cmapB), axis=1)
Of course, this is pseudocode, but is there some way to do this with good old numpy and matplotlib without installing a whole new package?
Instead of creating the two interim images like my answer above, an alternative way is to make the two arrays using imshow, like in the example below.
We will grab the numpy array from the imshow object using ._rgbacache, but to generate this you have to display the imshow object on an axis, hence the fig and ax at the beginning.
import numpy as np
import matplotlib.pyplot as plt
# Need to display the result of imshow on an axis
fig=plt.figure()
ax=fig.add_subplot(111)
# Save fig a with one cmap
a=np.random.rand(20,20)
figa=ax.imshow(a,cmap='jet')
# Save fig b with a different cmap
b=np.random.rand(20,20)
figb=ax.imshow(a,cmap='copper')
# Have to show the figure to generate the rgbacache
fig.show()
# Get the array of data
figa=figa._rgbacache
figb=figb._rgbacache
# Stitch the two arrays together
figc=np.concatenate((figa,figb),axis=1)
# Save without a cmap, to preserve the ones you saved earlier
plt.imsave('figc.png',figc,cmap=None)
EDIT:
To do this with imsave and a file-like object, you need cStringIO:
import numpy as np
import matplotlib.pyplot as plt
from cStringIO import StringIO
s=StringIO()
t=StringIO()
# Save fig a with one cmap to a StringIO instance. Need to explicitly define format
a=np.random.rand(20,20)
plt.imsave(s,a,cmap='jet',format='png')
# Save fig b with a different cmap
b=np.random.rand(20,20)
plt.imsave(t,b,cmap='copper',format='png')
# Return to beginning of string buffer
s.seek(0)
t.seek(0)
# Get the array of data
figa=plt.imread(s)
figb=plt.imread(t)
# Stitch the two arrays together
figc=np.concatenate((figa,figb),axis=1)
# Save without a cmap, to preserve the ones you saved earlier
plt.imsave('figc.png',figc,cmap=None)
You can use imsave to save both images with the desired cmaps first, then reopen them with imread, concatenate the arrays, and then use imsave again to save the concatenated figure with cmap set to None
import matplotlib.pyplot as plt
import numpy as np
# Save fig a with one cmap
a=np.random.rand(200,200)
plt.imsave('figa.png',a,cmap='jet')
# Save fig b with a different cmap
b=np.random.rand(200,200)
plt.imsave('figb.png',a,cmap='copper')
# Reopen fig a and fig b
figa=plt.imread('figa.png')
figb=plt.imread('figb.png')
# Stitch the two figures together
figc=np.concatenate((figa,figb),axis=1)
# Save without a cmap, to preserve the ones you saved earlier
plt.imsave('figc.png',figc,cmap=None)
Figure a, with jet cmap
Figure b, with copper cmap
Figure c