I have a table with 4 rows.First 2 rows, column 0 must be spanned, last 2 rows, column 0 must be spanned too.
This is the piece of code I use but at the time of the second span I get
QTableView :: setSpan: span cannot overlap
table.setRowCount(0)
new_row = 0
table.insertRow(new_row)
table.setRowHeight(new_row, 20)
table.setSpan(0, 0, 2, 1) ### <------
cell = QTableWidgetItem(str('AA'))
table.setItem(new_row, 0, cell)
a = 1
while a <= 10:
cell = QTableWidgetItem(str(a))
table.setItem(new_row, a, cell)
a += 1
new_row += 1
table.insertRow(new_row)
table.setRowHeight(new_row, 20)
a = 1
while a <= 10:
cell = QTableWidgetItem(str('CC'))
table.setItem(new_row, a, cell)
a += 1
new_row += 1
table.insertRow(new_row)
table.setRowHeight(new_row, 20)
table.setSpan(2, 0, 2, 1) ### <------
cell = QTableWidgetItem(str('BB'))
table.setItem(new_row, 0, cell)
The problem is that you are inserting a row within the previously set span. Spanning is dynamic, not fixed: if you insert elements between cells that include the spanning, their span is expanded.
If the model already had 2 rows, setting a 2-row span would make the first row span to the second one. Now, consider: what you should happen if you inserted a row between the first and the second? You would expect that the spanning should then extend to include all three rows, wouldn't you?
When you create the first row and set the first span, although there is only one row, the internal "span collection" will still keep that reference. When you insert a row at index 1 (meaning, between 0 and 1), the span is expanded as explained before: including rows 0 to 2, the first three rows. And that's even if there are still only two rows.
The error, then, comes from the fact that you're finally adding that third row (which is included in the span above), and when you try to set the second span, it won't work because it would overlap the previous one, because you want it to start from the third row.
The solution is simple: only set spans as soon as their rows or columns exist, not before.
In your case, move the first setSpan() after adding the second row. Consequentially, you should do the same for the second setSpan() only when its "spanned" rows are actually added (as right now, you're doing the same mistake).
Related
On python im trying to check if from a day to the next one (column by column), by ID, the values, if not all equal to zero, are correctly incremented by one or if at some point the value goes back to 0, then the next day it is either still equal to zero or incremented by one.
I have a dataframe with multiple columns, the first column is named "ID". All other columns are integers which names represent a day followed by the next day like this :
I need to check if for each ID :
all the columns (i.e for all of the days) are equal to 0 then create new column named "CHECK" which equals to 0 meaning there is no error ;
if not then look column after column and check if the value in the next column is greater than the previous column value (i.e the day before) and just incremented by 1 (e.g from 14 to 15 and not 14 to 16) then "CHECK" equals to 0 ;
if these conditions aren't satisfied it means that the next column is either equal to the previous column or lower (but not equal to zero) and in both cases it is an error then "CHECK" equals to 1 ;
But if the next value column is lower and equal to 0 then the next one to it must be either still 0 or incremented by 1. Each time it comes back to zero it must be followed by zero or incremented by 1
Each time there is a column in which the calculation comes back to zero, the next columns should either be equal to zero or getting +1 value.
If i explained everything correctly then in this example, the first two IDs are correct and their variable "CHECK" must be equal to 0 but the next ID should have a "CHECK" value 1.
I hope this is not confusing..thanks.
I tried this but would like to not use the column name but its index/position. Code not finished.`
df['check'] = np.where((df['20110531']<=df['20110530']) & ([df.columns!="ID"] != 0),1,0)
You could write a simple function to go along each row and check for your condition. In the example code below, I first set the index to ID.
df = df.set_index('ID')
def func(r):
start = r[0]
for j,i in enumerate(r):
if j == 0:
continue
if i == 0 or i == start +1:
start = i
else:
return 1
return 0
df['check'] = df.apply(func, axis = 1)
if you want to keep the original index the don't reset and use df['check'] = df.iloc[:,1:].apply(func, axis = 1)
I'm working with a large dataset that includes all police stops in my city since 2014. The dataset has millions of rows, but sometimes there are multiple rows for a single stop (so, if the police stopped a group of 4 people, it is included in the database as 4 separate rows even though it's all the same stop). I'm looking to create a new column in the dataset orderInStop, which is a count of how many people were stopped in sequential order. The first person caught up in the stop would have a value of 1, the second person a value of 2, and so on.
To do so, I have used the groupby() function to group all rows that match on time & location, which is the indication that the rows are all part of the same stop. I can manage to create a new column that includes the TOTAL count of the number of people in the stop (so, if there were 4 rows with the same time & location, all four rows have a value of 4 for the new orderInStop variable. But I need the first row in the group to have a value of 1, the second a value of 2, the third 3, and the fourth 4.
Below is my code attempt at iterating through each group I've created to sequentially count each row within each group, but the code doesn't quite work (it populates the entire column rather than each row within the groups). Any help to tweak this code would be much appreciated!
Note: I also tried using logical operators in a for loop, to essentially ask IF the time & location column values match for the current and previous rows, but ran into too many problems with 'the truth values of a Series is ambiguous' errors, so instead I'm trying to use groupby().
Attempt that creates a total count rather than sequential count:
df['order2'] = df.groupby(by=["Date_Time_Occur", "Location"])['orderInStop'].transform('count')
Attempt that fails, to iterate through each row in each group:
df['order3'] = 1
grp = df.groupby(by=["Date_Time_Occur", "Location"])
for name, groups in grp:
count = 1
for row in groups:
df['order3'] = count
count = count + 1
In your example for row in groups iterates over the column names, since groups is a DataFrame.
To iterate over each row you could do
df['order3'] = 1
grp = df.groupby(by=["Date_Time_Occur", "Location"])
for name, groups in grp:
count = 1
for i, row in groups.iterrows(): # i will be index, row a pandas Series
df['order3'] = count
count = count + 1
Note that your solution relies on pandas groupby to preserve row order. This should be the case, see this question, but there is very likely a shorter & safer solution (see fsimonjetz comment for a starting point).
I am trying to compare all rows within a group to check if a condition is fulfilled. If the condition is not fulfilled, I set the new column to True, else False. The issue I am having is finding a neat way to compare all rows within each group. I have something that works but will not work where there are a lot of rows in a group.
for i in range(8):
n = -i-1
cond=(((df['age']-df['age'].shift(n))*(df['weight']-df['weight'].shift(n)))<0)&(df['ref']==df['ref'].shift(n))&(df['age']<7)&(df['age'].shift(n)<7)
df['x'+i] = cond.groupby(df['ref']).transform('any')
df.loc[:,'WFA'] = 0
df.loc[(df['x0']==False)&(df['x1']==False)&(df['x2']==False)&(df['x3']==False)&(df['x4']==False)&(df['x5']==False)&(df['x6']==False)&(df['x7']==False),'WFA'] = 1
To iterate through each row, I have created a loop that compares adjacent rows (using shift). Each loop represents the next adjacent row. In effect, I am able to compare all rows within a group where the number of rows within a group is 8 or less. As you can imagine, it becomes pretty cumbersome as the number of rows grows large.
Instead of creating of column for each period in shift, I want to see if any row matches the condition with any other row. Then set the new column 'WFA' True or False.
If anyone is interested, I post the answer to my own question here (although it is very slow):
df.loc[:,'WFA'] = 0
for ref, gref in df.groupby('ref'):
count=0
for r_idx, row in gref.iterrows():
cond = ((((row['age']-gref.loc[gref['age']<7, 'age'])*(row['weight']-gref.loc[gref['age']<7, 'weight']))<0).any())&(row['age']<7)
if cond==False:
count+=1
if count==len(gref):
df.loc[df['ref']==ref, 'WFA'] = 1
I have a workbook with a number of sheets that I want to format after it's created, and I want to alter the colors of the header row based on column. For example, I want the first 9 columns to be one color, then column 10 should be another, then all the rest should be a third color.
This is what I am looping through...it sort of works, but all the cells in row 0 end up the same color; the last color assigned always overwrites the previous columns.
visitFormat = mtbook.add_format({'bg_color':'#e9ccfc'})
cognotesFormat = mtbook.add_format({'bg_color':'#d2eff2'})
filedateFormat = mtbook.add_format({'bg_color':'#8cbcff'})
for worksheet in mtbook.worksheets():
print(worksheet)
# for every column
for i in range(len(subreportCols)):
# set header bgcolor based on current column (i)
if [i] in range(0,11):
useheader = visitFormat
elif [i] == 10:
useheader = cognotesFormat
else:
useheader = filedateFormat
# Write the value from cell (first row, column=1) back into that cell with formatting applied
worksheet.write(0, i, subreportCols[i], useheader)
I'm confused by this, since I thought it was writing each column separately. Do I need to do this cell by cell somehow?
Thank you!
Solved it through troubleshooting, leaving up in case it helps someone else (there is an "Answer Your Question" button, after all).
In this line:
if [i] in range(0,11):
...what I thought I was doing was using [i] as a reference to the i'th value in my list, but I was actually referencing the WHOLE list. I swapped out [i] for just i, and that worked fine.
I'm trying to read through a CSV file that has a couple thousand rows and 3 columns of data. I'm successfully reading through the first and second column, but when I attempt to read through the third column I get an out of range error. In other words:
row=0
rowMax = len(AudioAngle)
while row < rowMax:
print (AudioAngle[row][0])
print (AudioAngle[row][1])
row=row+1
both work and when I add in
print (AudioAngle[row][2])
things only work until the 274th row.Looking at my CSV file I see this at that line.
00:09.0 0 0
00:09.0 0 0
00:09.0 0 0
00:09.1 <--- line 274
00:09.1 0 0
00:09.1 0 0
00:09.2 0 0
The code has no issue with the empty space in the second column but throws the error in the third column.
Why is this third column throwing an index out of range error at me when I try to read through it?
The parser might just use the space as a separator - thus the space between both first and second, and the second and third column could be seen as separating the first cell from a empty cell in the second column. To get rid of the error, just check for the sublist length! (And please use a for loop...)
for row in AudioAngle:
print(row[0])
print(row[1])
if len(row) >= 3:
print(row[2])
It makes sense that you will get an index out of range on the 274 row because [1] and [2] don't exist.
If you data may or may not be present, as in the case on line 274, you will need to check to see if it exists before you attempt to use it:
if (AudioAngle[row][0]):
print (AudioAngle[row][0])