Sorting Excel by 4 columns using Python (using win32com?) - python

I've been trying to sort my spreadsheet by 4 columns. Using win32com, I have managed to sort by 3 columns using the below code:
excel = win32com.client.Dispatch("Excel.Application")
wb= excel.Workbooks.Open('.xlsx')
ws= wb.worksheets[0]
ws.Range(D6:D110).Sort(Key1=ws.Range('D1'), Order1=1, Key2=ws.Range('E1'), Order2=2, Key3=ws.Range('G1'), Order3=3, Orientation=1)
However, when I try to add Key4, it says Key4 is an unexpected keyword argument. Is the Range.Sort function limited to only 3 keys? Is there a way to add a 4th?
Is there maybe another way to do this using pandas or openpyxl?
Thanks in advance!

Try reading in the excel sheet then sorting by header names. This assumes that your excel sheet is formatted correctly like a CSV.
import pandas as pd
df = pd.read_excel('filename.xlsx')
df = df.sort_values(['key1','key2','key3','key4'], axis=1)
df.to_excel('filename2.xlsx')

Simply sort twice or however many times needed in series of three keys.
xlAscending = 1
xlSortColumns = 1
xlYes = 1
ws.Range(D6:D110).Sort(Key1=ws.Range('D1'), Order1=xlAscending,
Key2=ws.Range('E1'), Order2=xlAscending,
Key3=ws.Range('G1'), Order3=xlAscending,
header=xlYes, Orientation=xlSortColumns)
# FOURTH SORT KEY (ADJUST TO NEEDED COLUMN)
ws.Range(D6:D110).Sort(Key1=ws.Range('H1'), Order1=xlAscending,
header=xlYes, Orientation=xlSortColumns)
By the way your Order numbers should only be 1, 2, or -4135 per the xlSortOrder constants.

Related

Python - Linking columns in Excel for sorting

The problem that I have to solve:
I'm trying to automate several processes in excel. I'm currently stuck on the first one. (Also I'm pretty weak at using excel so I apologize in advance if some of the things I saw don't make sense. I scraped data from the internet and inputted into an excel file. I concat'ed that data with a spreadsheet I already had. Here's the code I used to combine files.
import numpy as np
import pandas as pd
def MergeFiles():
#find both csv files on computer
baseData = pd.read_csv('pathname') #keep this on the left
scrapedData = pd.read_csv('pathname') #keep this on the right
mergedFile = pd.concat([baseData, scrapedData], axis = 1)
mergedFile.to_csv('pathname', index = False)
MergeFiles()
What I want to do:
Col1 Col2
c 1
b 2
a 3
-Alphabetically Order Col 1 and values in col2 also shift
Col1 Col2
a 3
b 2
c 1
I'm trying to link columns together so if I try to sort all rows go through the same position shift.
Also any help would be appreciated, I tried looking into Pandas documentation and I couldn't find anything related to this problem. I probably missed something so any help would be appreciated!
So apparently the pandas library does all of this automatically through sort_values()
So
scrapedData = scrapedData.sort_values(by = ['colName'], ascending=True,) #sort the scrapedData
scrapedData.to_csv('pathName', index = False) #replace the file
would do the trick

How do I extract variables that repeat from an Excel Column using Python?

I'm a beginner at Python and I have a school proyect where I need to analyze an excel document with information. It has aproximately 7 columns and more than 1000 rows.
Theres a column named "Materials" that starts at B13. It contains a code that we use to identify some materials. The material code looks like this -> 3A8356. There are different material codes in the same column they repeat a lot. I want to identify them and make a list with only one code, no repeating. Is there a way I can analyze the column and extract the codes that repeat so I can take them and make a new column with only one of each material codes?
An example would be:
12 Materials
13 3A8356
14 3A8376
15 3A8356
16 3A8356
17 3A8346
18 3A8346
and transform it toosomething like this:
1 Materials
2 3A8346
3 3A8356
4 3A8376
Yes.
If df is your dataframe, you only have to do df = df.drop_duplicates(subset=['Materials',], keep=False)
To load the dataframe from an excel file, just do:
import pandas as pd
df = pd.read_excel(path_to_file)
the subset argument indicates which column headings you want to look at.
Docs: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.drop_duplicates.html
For the docs, the new data frame with the duplicates dropped is returned so you can assign it to any variable you want. If you want to re_index the first column, take a look at:
new_data_frame = new_data_frame.reset_index(drop=True)
Or simply
new_data_frame.reset_index(drop=True, inplace=True)

Force Pandas to keep multiple columns with the same name

I'm building a program that collects data and adds it to an ongoing excel sheet weekly (read_excel() and concat() with the new data). The issue I'm having is that I need the columns to have the same name for presentation (it doesn't look great with x.1, x.2, ...).
I only need this on the final output. Is there any way to accomplish this? Would it be too time consuming to modify pandas?
you can create a list of custom headers that will be read into excel
newColNames = ['x','x','x'.....]
df.to_excel(path,header=newColNames)
You can add spaces to the end of the column name. It will appear the same in a Excel, but pandas can distinguish the difference.
import pandas as pd
df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['x','x ','x '])
df
x x x
0 1 2 3
1 4 5 6
2 7 8 9

Reading values in column x from specific worksheets using pandas

I am new to python and have looked at a number of similar problems on SO, but cannot find anything quite like the problem that I have and am therefore putting it forward:
I have an .xlsx dataset with data spread across eight worksheets and I want to do the following:
sum the values in the 14th column in each worksheet (the format, layout and type of data (scores) is the same in column 14 across all worksheets)
create a new worksheet with all summed values from column 14 in each worksheet
sort the totaled scores from highest to lowest
plot the summed values in a bar chart to compare
I cannot even begin this process because I am struggling at the first point. I am using pandas and am having trouble reading the data from one specific worksheet - I only seem to be able to read the data from the first worksheet only (I print the outcome to see what my system is reading in).
My first attempt produces an `Empty DataFrame':
import pandas as pd
y7data = pd.read_excel('Documents\\y7_20161128.xlsx', sheetname='7X', header=0,index_col=0,parse_cols="Achievement Points",convert_float=True)
print y7data
I also tried this but it only exported the entire first worksheet's data as opposed to the whole document (I am trying to do this so that I can understand how to export all data). I chose to do this thinking that maybe if I exported the data to a .csv, then it might give me a clearer view of what went wrong, but I am nonethewiser:
import pandas as pd
import numpy as np
y7data = pd.read_excel('Documents\\y7_20161128.xlsx')
y7data.to_csv("results.csv")
I have tried a number of different things to try and specify which column within each worksheet, but cannot get this to work; it only seems to produce the results for the first worksheet.
How can I, firstly, read the data from column 14 in every worksheet, and then carry out the rest of the steps?
Any guidance would be much appreciated.
UPDATE (for those using Enthought Canopy and struggling with openpyxl):
I am using Enthought Canopy IDE and was constantly receiving an error message around openpyxl not being installed no matter what I tried. For those of you having the same problem, save yourself lots of time and read this post. In short, register for an Enthought Canopy account (it's free), then run this code via the Canopy Command Prompt:
enpkg openpyxl 1.8.5
I think you can use this sample file:
First read all columns in each sheet to list of columns called y7data:
y7data = [pd.read_excel('y7_20161128.xlsx', sheetname=i, parse_cols=[13]) for i in range(3)]
print (y7data)
[ a
0 1
1 5
2 9, a
0 4
1 2
2 8, a
0 5
1 8
2 5]
Then concat all columns together, I add keys which are used for axis x in graph, sum all columns, remove second level of MultiIndex (a, a, a in sample data) by reset_index and last sort_values:
print (pd.concat(y7data, axis=1, keys=['a','b','c']))
a b c
a a a
0 1 4 5
1 5 2 8
2 9 8 5
summed = pd.concat(y7data, axis=1, keys=['a','b','c'])
.sum()
.reset_index(drop=True, level=1)
.sort_values(ascending=False)
print (summed)
c 18
a 15
b 14
dtype: int64
Create new DataFrame df, set column names and write to_excel:
df = summed.reset_index()#.
df.columns = ['a','summed']
print (df)
a summed
0 c 18
1 a 15
2 b 14
If need add new sheet use this solution:
from openpyxl import load_workbook
book = load_workbook('y7_20161128.xlsx')
writer = pd.ExcelWriter('y7_20161128.xlsx', engine='openpyxl')
writer.book = book
writer.sheets = dict((ws.title, ws) for ws in book.worksheets)
df.to_excel(writer, "Main", index=False)
writer.save()
Last Series.plot.bar:
import matplotlib.pyplot as plt
summed.plot.bar()
plt.show()
From what I understand, your immediate problem is managing to load the 14th column from each of your worksheets.
You could be using ExcelFile.parse instead of read_excel and loop over your sheets.
xls_file = pd.ExcelFile('Documents\\y7_20161128.xlsx')
worksheets = ['Sheet1', 'Sheet2', 'Sheet3']
series = [xls_file.parse(sheet, parse_cols=[13]) for sheet in worksheets]
df = pd.DataFrame(series)
And from that, sum() your columns and keep going.
Using ExcelFile and then ExcelFile.parse() has the advantage to load your Excel file only once, and iterate over each worksheet. Using read_excel makes your Excel file to be loaded in each iteration, which is useless.
Documentation for pandas.ExcelFile.parse.

Reference Excel in Python

I am writing a python code for beam sizing. I have an Excel workbook from AISC that has all the data of the shapes and other various information on the cross-sections. I would like to be able to reference data in particular cells in this Excel workbook in my python code.
For example if the width of rectangle is 2in and stored in cell A1 and the height is 10in and stored in cell B1 I want to write a code in python that somehow pulls in cell A1 and B1 and multiply them.
I do not need to export back into excel I just want to make python do all the work and use excel purely as reference material.
Thank you in advance for all your advice and input!!
Try pandas as well...might be easier to work with than lists in this case
DATA :
Width Height
4 2
4 4
1 1
4 5
Code
import pandas as pd
#read the file
beam = pd.read_csv('cross_section.csv')
beam['BeamSize'] = beam['Width']*beam['Height'] #do your calculations
Output:
>>> beam
Width Height BeamSize
0 4 2 8
1 4 4 16
2 1 1 1
3 4 5 20
4 2 2 4
You can slice and dice the data as you wish.
For eg, lets say you want the fifth beam :
>>> beam.ix[4]
Width 2
Height 2
BeamSize 4
Name: 4, dtype: int64
Check this for more info:
http://pandas.pydata.org/pandas-docs/stable/
You can read directly from excel as well..
Thank you for you inputs. I have found the solution I was looking for by using Numpy.
data = np.loadtxt('C:\Users[User_Name]\Desktop[fname].csv', delimiter=',')
using that it took the data and created an array with the data that I needed. Now I am able to use the data like any other matrix or array.
If you don't mind adding a (somewhat heavy) dependency to your project, pandas has a read_excel function that can read a sheet from an Excel workbook into a pandas DataFrame object, which acts sort of like a dictionary. Then reading a cell would just amount to something like:
data = pd.read_excel('/path/to/file.xls')
cell_a1 = data.loc[1, 'a'] # or however it organizes it on import
For future readers of this question, it should be mentioned that xlrd is the "most exact" solution to your requirements. It will allow you to read data directly from an Excel file (no need to convert to CSV first).
Many other packages that read Excel files (including pandas) use xlrd themselves to provide that capability. They are useful, but "heavier" than xlrd (larger, more dependencies, may require compilation of C code, etc.).
(Incidentally, pandas happens to use both xlrd and NumPy.)

Categories