【问题标题】:Removing a nested key value pair from dictionary based on value in dataframe根据数据框中的值从字典中删除嵌套的键值对
【发布时间】:2020-08-11 21:04:49
【问题描述】:

这个问题一方面帮助一方面帮助好奇心,所以我有一个字典,一旦我的所有条件都被迭代完,我就会将它附加到一个列表中:

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)

基本上,我正在向 dict l 添加多个键和值,我的主要问题是,提供 'id' == 'None' 的值之一我不想将整个键值对添加到字典中。

所以最好的情况输出如下:

final_l = {'external': {'om': {'id' : '123'},
                        'wd': {'id': '456'},
                        'wk': {'id': '789'}
                                }}

但是:根据其相应的数据帧值提供这些值之一== 'None',我不想用 None 替换“id”,我根本不想在那里,所以最好说@ 987654325@ 然后输出字典看起来像:

final_l = {'external': {'om': {'id' : '123'},
                        'wd': {'id': '456'}
                                }}

但我唯一能得到的是:

final_l = {'external': {'om': {'id' : '123'},
                        'wd': {'id': '456'},
                        'wk': {'id': 'None'}
                                }}

这对我的用例来说不是最优的。那么,如何根据对应的数据帧值从字典中删除(甚至不添加)特定的键值对?此外,如果有更好的方法可以做到这一点,我非常愿意接受,因为这“有效”,但上帝不优雅。

编辑示例数据框:

   id_check   om    wd    wk
0   Add all  123  None   789
1   Add all  472   628  None
2  Add None  528   874   629

【问题讨论】:

  • 你能添加一个数据框的样本吗?
  • @MrNobody33 编辑了帖子,下面是示例 df。
  • 'Add_all' 的另一种情况是什么?我的意思是,如果row['id_check'] != 'Add all' 会发生什么? @SebastianGoslin
  • @MrNobody33 Add None 这是一个传递,我在这个循环中创建的字典的特定部分不会被附加。
  • 准备好了,刚刚添加了一个方法@SebastianGoslin!

标签: python pandas dictionary


【解决方案1】:

我正在编辑我之前的答案,这既基于您尝试更改字典而不是数据框的回复,也因为我之前的答案不正确。

我找不到一种方法来使用一种简单的方法来完成您的要求 - 例如。列表理解,但能够使用我创建的这个转换器来做到这一点:

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)

示例用法:

>>> 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']}

【讨论】:

  • 所以完整的数据框有几百行把整个东西放在这里是不切实际的。但是,如果我正在阅读您写的正确内容,它将删除== None 的所有行,在这种情况下这不是最佳的,因为某些值可以具有所有ids 或一些,或没有,它的变化。
  • 对,但您可以将其纳入我所说的内容中。你可以有一个函数来检查你不想要的类型和值。然后你会得到类似{i: j for i, j in d.items() if not is_wrong_value(j)} 的东西,其中is_wrong_value() 表示函数。也就是说,除非我误解了您所说的“某些值可以具有所有 id 或某些或没有,它是多种多样的”的意思。
  • 啊,我明白了,所以样本 df 有一行可能出现的所有值。但是在实际的 df 中有几千行,其中有些可能对每列都有正确的值,有些可能没有,所以它在整个数据帧中并不统一。所以我想创建一个我在数据框中只出现值(不是None)的问题中创建的格式的字典。
  • 我已经更新了示例,希望更有意义。
  • 在您最近一次编辑之前,您似乎正在使用 pd Dataframe 构造函数中的数据字段对其进行初始化。我的印象是这个问题是基于实例创建的——但如果你已经有一个 df,那么我认为最好/最 Pythonic 的事情是使用 pandas 的实际 api。即df.dropna。更多信息可以在here找到。
【解决方案2】:

IIUC,你可以试试to_dictdropnaeqto_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()

输出:

final_l
[{'external': {'om': 123.0, 'wk': '789'}},
 {'external': {'om': 472.0, 'wd': '628'}}]

【讨论】:

  • 遗憾的是,输出中仍然包含带有“None”的键(除非是拼写错误),因此对于您的 final_l[0],所需的输出将是 {'external': {'om': 123.0, 'wk': '789'}}final_l[1] {'external': {'om': 472.0, 'wd': '628'}} ,我正在尝试从字典中删除 None 的密钥。
  • 拜托,看看更新@SebastianGoslin 有用吗?
【解决方案3】:

所以我尝试了提供的答案,我遇到的最大问题是真实性评估和速度。我编写了这个“有效”的代码,但从效率的角度来看我不太满意:

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)

哪些输出:

{'external': {'om': {'id' : '123'},
                     'wd': {'id': '456'},
                     'wk': {'id': '789'}}}

并忽略值 == None 的键:

{'external': {'om': {'id' : '123'},
                     'wd': {'id': '456'}}}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-20
    • 1970-01-01
    • 2019-06-04
    • 2021-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多