Reputation: 497
The question is one part help one part curiosity, so I have a dict that I'm appending to a list once all my conditions have been iterated through:
for col, row in df.iterrows():
up_list = []
if row['id_check'] == 'Add all':
l = {'external': {'om': {'id' : row['posm']},
'wd': {'id': row['wdp']},
'wk': {'id': row['tw'].replace('ru: ', '')}
}
}
up_list.append(l)
Basically, I'm adding multiple keys and values to the dict l, and my main question is, provided one of values for 'id' == 'None'
I don't want to add the entire key value pair to the dictionary.
So best case output looks like:
final_l = {'external': {'om': {'id' : '123'},
'wd': {'id': '456'},
'wk': {'id': '789'}
}}
BUT: provided one of those values == 'None'
based on its corresponding dataframe value, I don't want to replace the 'id' with None, I don't want to have it there at all, so ideally say 'wk' == 'None'
then the output dict would look like:
final_l = {'external': {'om': {'id' : '123'},
'wd': {'id': '456'}
}}
But the only thing I can get is:
final_l = {'external': {'om': {'id' : '123'},
'wd': {'id': '456'},
'wk': {'id': 'None'}
}}
Which is not optimal for my use case. So, How do you delete (or not even add) specific key value pairs from a dictionary based on its corresponding dataframe value? Also if there is a better way of doing this I'm very to open to this, as this "works" but by god is it not elegant.
EDIT Sample Dataframe:
id_check om wd wk
0 Add all 123 None 789
1 Add all 472 628 None
2 Add None 528 874 629
Upvotes: 0
Views: 645
Reputation: 497
So I tried the provided answers, and the biggest issue I ran into was truth evaluation and speed. I coded this which "works" but I'm not too happy with it from an efficiency standpoint:
if row['id_check'] == 'Add all IDs':
link_d, ex_link = {}, {}
if row['posm'] != 'None':
link_d['om'] = {'id': row['posm']}
if row['pd'] != 'None':
link_d['wd'] = {'id': row['pd']}
if row['tw'] != 'None':
link_d['wk'] = {'id': row['tw']}
ex_link['external'] = link_d
up_list.append(ex_link)
up_d[row['id']] = up_list
all_list.append(up_d)
Which outputs:
{'external': {'om': {'id' : '123'},
'wd': {'id': '456'},
'wk': {'id': '789'}}}
and ignores keys where the value == None
:
{'external': {'om': {'id' : '123'},
'wd': {'id': '456'}}}
Upvotes: 0
Reputation: 6483
IIUC, you could try with to_dict
, dropna
, eq
and to_list
:
final_l=df[df['id_check'].eq('Add all')].drop('id_check',1)
.apply(lambda x : {'external':x.dropna().to_dict()},axis=1)
.to_list()
Output:
final_l
[{'external': {'om': 123.0, 'wk': '789'}},
{'external': {'om': 472.0, 'wd': '628'}}]
Upvotes: 1
Reputation: 1355
I am editing my previous answer both based on your response that you are trying to alter the dictionary and not the dataframe and because my previous answer was incorrect.
I couldn't find a way to do what you are asking using a nice simple way - e.g. list comprehension, but was able to do it with this converter I created:
class Converter:
def __init__(self):
self.rows = []
self.cols = []
@classmethod
def from_dict(cls, d):
conv_df = cls()
conv_df.cols = list(d.keys())
conv_df.rows = list(zip(*d.values()))
return conv_df
def as_dict(self):
vals = []
for idx, _ in enumerate(self.cols):
vals.append([j[idx] for j in self.rows if None not in j])
return {k: v for k, v in zip(self.cols, vals)
Example usage:
>>> z = {'a': [1, 2, 3], 'b': ['a', 'b', 'c'], 'c': ['q', 'r', None]}
>>> conv = Converter.from_dict(z)
>>> conv.cols
['a', 'b', 'c']
>>> conv.rows
[(1, 'a', 'q'), (2, 'b', 'r'), (3, 'c', None)]
>>> "Get as dict and we expect last row not to appear in it:"
'Get as dict and we expect last row not to appear in it:'
>>> conv.as_dict()
{'a': [1, 2], 'b': ['a', 'b'], 'c': ['q', 'r']}
Upvotes: 1