For example, if I iterate over a query using:
for row in cursor:
And I want to make a comparison like:
if row[0] == previousrow[0]:
#do something
How can I actually access the previous row?
If you wanted to access the previous row from your for loop, you could use the following code.
previousrow = None
for row in cursor:
if (!(previousrow is None)):
# do your comparison with previous row and row here
previousrow = row
I don't write Python, but I think this compiles and should work for you.
Related
I want to get an individual row from the QueryJob in BQ. My query: select count(*) from ... returns a single row & I want to read the count value which is its first column. So if I can get the first row then I can do row[0] for the first column. I can iterate: row in queryJob but since I require only the first row this seems unneccesary.
Below is what I've tried:
row = self.client.query(count_query)
count = row.result()[0]
This gives an error:
'QueryJob' object is not subscriptable"
How can I get individual rows from queryJob by the row index?
Just do:
row = self.client.query(count_query)
result = row.result().total_rows
This will give the count from the query
you can use to_dataframe():
result = self.client.query(count_query).to_dataframe()
#if you want to result as a integer:
result = self.client.query(count_query).to_dataframe()['first_column_name'].iat[0]
Good morning guys! quick question for Openpyxl:
I am working with Python editing a xlsx document and generating various stats. Part of my script is to generate max values of a cell range :
temp_list=[]
temp_max=[]
for row in sheet.iter_rows(min_row=3, min_col=10, max_row=508, max_col=13):
print(row)
for cell in row:
temp_list.append(cell.value)
print(temp_list)
temp_max.append(max(temp_list))
temp_list=[]
I would also like to be able to print the string of the header of the column that contains the max value for the cell range desired. My data structure looks like this :
Any idea on how to do so?
Thanks!
This seems like a typical INDEX/MATCH Excel problem.
Have you tried retrieving the index for the max value in each temp_list?
You can use a function like numpy.argmax() to get the index of your max value within your "temp_list" array, then use this index to locate the header and append the string to a new list called, say, "max_headers" which contains all the header strings in order of appearance.
It would look something like this
for cell in row:
temp_list.append(cell.value)
i_max = np.argmax(temp_list)
max_headers.append(cell(row = 1, column = i_max).value)
And so on and so forth. Of course, for that to work, your temp_list should be a numpy array instead of a simple python list, and the max_headers list would have to be defined.
First, Thanks Bernardo for the hint. I found a decently working solution but still have a little issue. Perhaps someone can be of assistance.
Let me amend my initial statement : here is the code I am working with now :
temp_list=[]
headers_list=[]
for row in sheet.iter_rows(min_row=3, min_col=27, max_row=508, max_col=32): #Index starts at 1 // Here we set the rows/columns containing the data to be analyzed
for cell in row:
temp_list.append(cell.value)
for cell in row:
if cell.value == max(temp_list):
print(str(cell.column))
print(cell.value)
print(sheet.cell(row=1, column=cell.column).value)
headers_list.append(sheet.cell(row=1,column=cell.column).value)
else:
print('keep going.')
temp_list = []
This formula works, but has a little issue : If, for instance, a row has the same value twice (ie : 25,9,25,8,9), this loop will print 2 headers instead of one. My question is :
how can I get this loop to take in account only the first match of a max value in a row?
You probably want something like this:
headers = [c for c in next(ws.iter_rows(min_col=27, max_col=32, min_row=1, max_row=1, values_only=True))]
for row in ws.iter_rows(min_row=3, min_col=27, max_row=508, max_col=32, values_only=True):
mx = max(row)
idx = row.index(mx)
col = headers[idx]
I'm creating a program where I need to check if a certain cell in a table equals a string value and, if it does not, to not change that value. Here is some snippet of the code for clarification:
if (db.execute("SELECT :rowchosen FROM userboard WHERE column=:columnchosen", rowchosen = rowchosen, columnchosen = columnchosen)) == '-'):
#change value of cell
else:
#go to a new page that displays an error
Yet, whenever I run this code, I always get an error because the value (I believe) prints as a dictionary value, something like {"row" = 'row'} of that sort. Any help/advice as to why this happens?
Are you sure that userboard is the database and not the table?
i think, here is what you want to do
conn = sqlite3.connect(db_file)
cur = conn.cursor()
cur.execute("SELECT * FROM userboard WHERE one=?", (columnchosen,))
rows = cur.fetchall()
for row in rows:
print(row)
now, in the loop for row in rows: you need to perform your check. For all the rows returned, you need to check each row for - in the appropriate column
also check out http://www.sqlitetutorial.net/sqlite-python/sqlite-python-select/
I have created a database with multiple columns and am wanting to use the data stored in two of the columns (named 'cost' and 'Mwe') to create a new column 'Dollar_per_KWh'. I have created two lists, one contains the rowid and the other contains the new value that I want to populate the new Dollar_per_KWh column. As it iterates through all the rows, the two lists are zipped together into a dictionary containing tuples. I then try to populate the new sqlite column. The code runs and I do not receive any errors. When I print out the dictionary it looks correct.
Issue: the new column in my database is not being updated with the new data and I am not sure why. The values in the new column are showing 'NULL'
Thank you for your help. Here is my code:
conn = sqlite3.connect('nuclear_builds.sqlite')
cur = conn.cursor()
cur.execute('''ALTER TABLE Construction
ADD COLUMN Dollar_per_KWh INTEGER''')
cur.execute('SELECT _rowid_, cost, Mwe FROM Construction')
data = cur.fetchall()
dol_pr_kW = dict()
key = list()
value = list()
for row in data:
id = row[0]
cost = row[1]
MWe = row[2]
value.append(int((cost*10**6)/(MWe*10**3)))
key.append(id)
dol_pr_kW = list(zip(key, value))
cur.executemany('''UPDATE Construction SET Dollar_per_KWh = ? WHERE _rowid_ = ?''', (dol_pr_kW[1], dol_pr_kW[0]))
conn.commit()
Not sure why it isn't working. Have you tried just doing it all in SQL?
conn = sqlite3.connect('nuclear_builds.sqlite')
cur = conn.cursor()
cur.execute('''ALTER TABLE Construction
ADD COLUMN Dollar_per_KWh INTEGER;''')
cur.execute('''UPDATE Construction SET Dollar_per_KWh = cast((cost/MWe)*1000 as integer);''')
It's a lot simpler just doing the calculation in SQL than pulling data to Python, manipulating it, and pushing it back to the database.
If you need to do this in Python for some reason, testing whether this works will at least give you some hints as to what is going wrong with your current code.
Update: I see a few more problems now.
First I see you are creating an empty dictionary dol_pr_kW before the for loop. This isn't necessary as you are re-defining it as a list later anyway.
Then you are trying to create the list dol_pr_kW inside the for loop. This has the effect of over-writing it for each row in data.
I'll give a few different ways to solve it. It looks like you were trying a few different things at once (using dict and list, building two lists and zipping into a third list, etc.) that is adding to your trouble, so I am simplifying the code to make it easier to understand. In each solution I will create a list called data_to_insert. That is what you will pass at the end to the executemany function.
First option is to create your list before the for loop, then append it for each row.
dol_pr_kW = list()
for row in data:
id = row[0]
cost = row[1]
MWe = row[2]
val = int((cost*10**6)/(MWe*10**3))
dol_pr_kW.append(id,val)
#you can do this or instead change above step to dol_pr_kW.append(val,id).
data_to_insert = [(r[1],r[0]) for r in dol_pr_kW]
The second way would be to zip the key and value lists AFTER the for loop.
key = list()
value = list()
for row in data:
id = row[0]
cost = row[1]
MWe = row[2]
value.append(int((cost*10**6)/(MWe*10**3)))
key.append(id)
dol_pr_kW = list(zip(key,value))
#you can do this or instead change above step to dol_pr_kW=list(zip(value,key))
data_to_insert = [(r[1],r[0]) for r in dol_pr_kW]
Third, if you would rather keep it as an actual dict you can do this.
dol_pr_kW = dict()
for row in data:
id = row[0]
cost = row[1]
MWe = row[2]
val = int((cost*10**6)/(MWe*10**3))
dol_pr_kW[id] = val
# convert to list
data_to_insert = [(dol_pr_kW[id], id) for id in dol_per_kW]
Then to execute call
cur.executemany('''UPDATE Construction SET Dollar_per_KWh = ? WHERE _rowid_ = ?''', data_to_insert)
cur.commit()
I prefer the first option since it's easiest for me to understand what's happening at a glance. Each iteration of the for loop just adds a (id, val) to the end of the list. It's a little more cumbersome to build two lists independently and zip them together to get a third list.
Also note that if the dol_pr_kW list had been created correctly, passing (dol_pr_kW[1],dol_pr_kW[0]) to executemany would pass the first two rows in the list instead of reversing (key,value) to (value,key). You need to do a list comprehension to accomplish the swap in one line of code. I just did this as a separate line and assigned it to variable data_to_insert for readability.
I want to insert my data which is stored in a sqlite table, to a QTableWidget. I use two for loop to find the data and index. after each iteration I print the data in console and it is OK but when it displays the table widget there is only the first row and the last row filled with the data.
Any idea to solve this problem?
It's obvious that tblTable is a QTableWidget!
Here is this part of the code:
cursor.execute('''SELECT * FROM MyTable''')
for index , form in enumerate(cursor.fetchall()):
i = 0
for item in form:
print(str(item))
self.tblTable.setItem(index, i, QtGui.QTableWidgetItem(str(item)))
i = i + 1
self.tblTable.insertRow(1)
You keep inserting your new row at position 1. What happens is that the previously entered data is then moved up one row, at which point you overwrite that data in the next loop.
So, first iteration everything is inserted in row 0, you add a row at index 1. Then you update row 1 with data, and insert another row at position 1, making the previously modified row move to row 2. Next loop, you overwrite the data on row 2, insert another empty row at position 1, moving the row with data to position 3 and you overwrite it again, etc., etc.
Set the row-count to 0 at the start, and insert rows as you need them before you insert your column data:
cursor.execute('''SELECT * FROM MyTable''')
self.tblTable.setRowCount(0)
for row, form in enumerate(cursor):
self.tblTable.insertRow(row)
for column, item in enumerate(form):
print(str(item))
self.tblTable.setItem(row, column, QtGui.QTableWidgetItem(str(item)))
I am not that familiar with the QtTableWidget, it could be that continually adding rows in not going to perform as well as setting the number of rows up front.
If sqlite's cursor.rowcount attribute is properly updated on your query (it not always is), you'd be better off calling .setRowCount with that value:
cursor.execute('''SELECT * FROM MyTable''')
self.tblTable.setRowCount(cursor.rowcount)
for row, form in enumerate(cursor):
for column, item in enumerate(form):
self.tblTable.setItem(row, column, QtGui.QTableWidgetItem(str(item)))
If the .rowcount value is not available (set to 1 or similar), perhaps first asking the database for the number of rows can help:
rowcount = cursor.execute('''SELECT COUNT(*) FROM MyTable''').fetchone()[0]
self.tblTable.setRowCount(rowcount)
cursor.execute('''SELECT * FROM MyTable''')
for row, form in enumerate(cursor):
for column, item in enumerate(form):
self.tblTable.setItem(row, column, QtGui.QTableWidgetItem(str(item)))
In all examples above, I also renamed you variables to something a little closer to their use, and used enumerate on the item loop as well. Last, but not least, the cursor can act as an iterator, meaning you can loop over rows directly without calling .fetchall() and rows will be fetched as needed.