Fill a dictionary with all cell values of given row - python

User sets values manually in all cells in a QTableWidget. The values of the first row of the table represent the values we want to store in a dictionary FirstRowDict. Second row values will be put in SecondRowDict and so on.
So from a table like one shown in the picture,
we want to end up in this example with FirstRowDict={0:10,1:20}
and SecondRowDict={0:30,1:40}
To achieve this i created a button and added an action that updates the target dictionaries when clicked:
def button_click():
for j in range(0,2):
FirstRowDict.update({i: float(str(tablewidget.itemAt(0,j).text()))})
#I put "0" in itemAt because first row is zero
#tablewidget = QTableWidget() declared earlier in the source code
SecondRowDict.update({i: float(str(tablewidget.itemAt(1,j).text()))})
print '1st_Row_Dict=%s'%1st_Row_Dict,'\n2nd_Row_Dict=%s'%2nd_Row_Dict
The output is not correct since the dictionaries are populated with same value and not the unique value of each cell.
I get FirstRowDict={0:10,1:10} and SecondRowDict={0:10,1:10}
It seems that i have to create a new item using QTableWidgetItem http://doc.qt.nokia.com/4.7-snapshot/qtablewidget.html#item
Python begginer, some advice would be appreciated.

Ah, I see the confusion. itemAt returns the item at the given position, but it's not row/column. It's the coordinate (think of it as pixel).
Yes, you should use item instead of itemAt.
You don't need a str if you're going to convert it to float. float() will work on a QString as if it was a str. And, instead of .update, you can just assign the new value to the key.
FirstRowDict[i] = float(tablewidget.item(0, j).text())

Related

Append Values at Dict in Python

I have following code and want now to add all items of "Produkt-Name" to a Dictionary
for col_number, element in enumerate(headings):
for row in ws.iter_rows():
if row[col_number].value is None:
continue
else:
if element == "Produkt-Name":
test = {"productname": row[col_number].value}
The Problem is, I only get the last item of it at the dictionary. I also tested the build in update function but got the last index too.
Every time your conditions are met (the two if statements) you create a new dictionary called "test", the proper syntax to add elements to a dict is :
my_dict[new_key] = value
if new_key already exists, then you will overwrite the old value with the new one, without creating a new key/value pair.
Hope this helps.
Also, as others already pointed out, please produce a minimal reproducible example, we at least need the structure of "headings" and what you would expect as an output.
if you want to have all items under the key 'productname' you can use:
test.setdefault("productname", []).append(row[col_number].value)
but if you want to have your values under different keys you need to set different key names.
Edit: for example: test[key1] = value1, test[key2] = value2, ...

How to append cell values in openpyxl directly

I'm trying to append cell value using openpyxl, by appending the value directly.
this works:
wb1=load_workbook('test.xlsx')
ws1=wb1.active
testlist=('two','three','four','five')
for i in testlist:
ws1['A1'].value = ws1['A1'].value +(' ') + i
print(ws1['A1'].value)
A1 has a value of "one", after the loop runs it has "one two three four five"
But is it possible to use the append method directly on the cell value?
for i in testlist:
ws1.append['A1'].value = i
however this throws an error
"TypeError: 'method' object does not support item assignment"
The error "method' object is not subscriptable" means that, you are treating an object as python dict or dict like object which the object isn't. Because the append method returns None.
As per documentation of openpyxl, You can worksheet.append via:
A list: all values are added in order, starting from the first column.
which is your case. simply doing the following should work:
wb1=Workbook()
ws1=wb1.active
testlist=('one','two','three','four','five')
# append each element side by side in a single row
ws1.append(testlist)
# To append each element vertical direction in new row you can un-comment next 2 lines.
#for entry in testlist:
# ws1.append([entry])
wb1.save('test.xlsx')
A dict: values are assigned to the columns indicated by the keys (numbers or letters). This might help if you are targeting a specific column.
Or To have more control simply use worksheet.cell.
You will need to move the tuple into a string and can add it to cell A1 like this.
wb1=Workbook()
ws1=wb1.active
testlist=('one','two','three','four','five')
myString = ' '.join(map(str, testlist))
myString.strip()
ws1['A1'].value = myString
wb1.save('test1.xlsx')

Pandas DataFrames Lists

So I created a new column in my dataframe using a list. Now every entry has the ‘[ ]’ squared parentheses around the text. How do I remove them? Please help! It seems easy but I’m not getting there. Code used:
df.insert(1, ‘Email’, emails_list, True)
Now all the data in the Email column is in [square brackets]. I want to remove those parentheses.
You probably have lists as values to each row in the column 'Email'. You can try the below code to take the first element of the list, and replace the original list with it.
df['Email'] = df['Email'].map(lambda x: x[0] if len(x)> 0 else '')
The above code takes each cell value of the column, and checks if it of non zero length. If it has non-zero length, then it replaces the list in the cell, with the first element of the list. Otherwise, it just replaces it with an empty string.
This should help. If the error persists, please check the type and shape of 'emails_list'

How to retrieve a sequence of records from a Pandas dataframe that contains a certain value at the end of one of the columns?

I'm using event based data, looking to only return rows that are in a certain sequence. Below is an example of a sequence and the structure of the data.
My issue is with returning a sequence like this, the idea is to search through the action_name column to find a goal entry and then return every pass/action that occurred leading up to the goal. The way to link the actions is by the possesion_number and match_id as these will be unique for each sequence.
I can complete the first part by returning all the pass and goal actions into a separate dataframe with below code but how do I retain sequences that only end with a goal?
pass_goal = data.loc[data.action_name.isin(['Attacking pass accurate',
'Non attacking pass accurate','Accurate key pass','goal'])]
I think there's a better way to approach the problem. First, aggregate up to the level of the possession, keeping the actions and some way to sequence them (second?)
posses = data.groupby('possession_number')[['second', 'action_name']].apply(lambda action: action.values.tolist()).reset_index(name='action_seq')
Then order the actions within and identify ones where the last action is a goal.
posses['ends_in_goal'] = posses.apply(lambda pos: sorted(pos['action_seq'])[-1][1] == 'goal', axis=1)
EDIT:
To clarify, the apply method evaluates a function on (in this case, with axis=1) rows and assigns the output to a new column.
Here's the function with a breakout:
lambda pos: # Define a lambda with the row as "pos"
sorted(pos['action_seq']) # Sort the "action_seq" list of tuples by the first tuple value, "second" (see above)
[-1][1] # Get the last tuple in the sorted list of tuples, and from the last tuple, get the second value, "action_name"
== 'goal' # Return True if the "action_name" of the last tuple in the sorted list of actions for that possession is "goal"
If you want to sort the actions in the possession by a different column, create the list of tuples with that column as the first tuple value (see ['second', 'action_name'] from above.) Then get the value for action_name from the appropriate place in the tuple.
Assuming that all your data is in df and that every goal has another pair of ['possion_code', 'match_id'], you could to something like the following:
goals = df.groupby(['posession_number', 'match_id']). \
filter(lambda grouped_df: (grouped_df['action_name'] == 'goal').any())

creating a mapping variable in python

This is a little extension to my previous problem. I have a variable known as region with values such as:
/health/blood pressure
/health/diabetes
/cmd/diagnosis
/fitness
/health
/health/type1 diabetes
Now I want to add one more variable known as region_map alongside with region variable which maps each region to a unique name such as Region1, Region2, so on as they appear sequentially in the column. So the output would look like:
/health/blood pressure Region1
/health/diabetes Region2
/cmd/diagnosis Region3
/fitness Region4
/health Region5
/health/type1 diabetes Region6
Also all the region values are unique.
Basically its a web related data, but not now its a stand alone task. In python shell I have imported the data which just consists of unique list of regions. Now first task was to remove the integer values, which I did successfully with the help of other members. Now I have around 2000+ entries for regions. Sample data as i mentioned above, you can see it. For subsequent analysis like merging it with other files, I want to add mapping variable to the existing column, which is region. So for each unique 2000+ entries I want separate mapping variable such as region 1, region 2, region 3, region 2000+. I have created a dictionary with following code:
mapping={region:index for index, region in enumerate(data.region)}
But problem is how to loop through it and replacing existing values with region 1, region 2 and so on. Basically as i explained I want to add one more column with each entry mapping to different region. Hope this explains you well!!
You can use a dictionary so you will have keys as names and the regions as values.
You can use it like this:
dict[key] = value
This will create a new key and assign a value for it.
You can put the key like this "/health/blood pressure" and then the value like this "Region 1".
When you refer to it:
dict["/health/blood pressure"]
It will return "Region 1".
To loop through the dictionary, do the following:
for i in dictionary:
# condition to see if you need to change the current value
dictionary[i] = "New Value" # The I represents the key in the dictionary.
For more information look in the python manual, cause these are just basic information for using dictionaries, and if you are doing a web service personally I would prefer using a DB for this. But again I don't know the bigger picture so its hard to say.
I assume that you already have an array list of the regions and needs new array list with the mapping of REGION and REGION MAP.
region = ["/health/blood pressure", "/health/diabetes", "/cmd/diagnosis" ,"/fitness", "/health", "/health/type1 diabetes"]
region_mapped = {}
region_count = len(region)
for region_index in range(0, region_count):
region_mapped[region[region_index]] = "Region-%s" % region_index
print(region_mapped)
As its available with LIST - DICT can not append/extend the elements.
As you will need key:value pair kind of elements then above example is best suited. Still you can make it even optimised by creating def.

Categories