【问题标题】:Pandas loop from leftmost column and change values by dictinoaryPandas 从最左列循环并按字典更改值
【发布时间】:2021-12-14 20:17:12
【问题描述】:

我有以下字典和数据框:

val_dict = {
    'key1': ['val1', 'val2', 'val3'], 
    'key2': ['val4', 'val5']
}

df = pd.DataFrame(data={'val5': [True, False, False], 
                        'val2': [False, True, False], 
                        'val3': [True, True, False], 
                        'val1': [True, False, True], 
                        'val4': [True, True, False],
                        'val6': [False, False, True]},
                        index=pd.Series([1, 2, 3], name='index'))
index val5 val2 val3 val1 val4 val6
1 True False True True True False
2 False True True False True False
3 False False False True False True

如何从左侧遍历数据框,以便如果列是 Trueval_dict 值中的其他列将变为 False

index val5 val2 val3 val1 val4 val6
1 True False True FALSE FALSE False
2 False True FALSE False True False
3 False False False True False True

例如,索引 1 具有 val5True,因此 val4 切换到 False,因为它们都分配给相同的 val_dict 键。同样,val2False,但 val3True,所以 val1 变成了 False。请注意,它应该跳过val6

我尝试将df 转换为带有df.to_dict('index') 的字典以使用两个字典。但是,字典是无序的,并且列的顺序很重要,所以我认为这可能会使代码出错。

【问题讨论】:

  • 3.6 版的字典是有序的
  • 如果我们要使用两个字典,这将如何实现?
  • 如果一行的所有 val 都为 False,是否应该将第一个设置为 True?
  • 如果一行的所有 val 都是 False,则该行应保持为 false

标签: pandas dataframe dictionary


【解决方案1】:

一种方法是结合分配和掩码:

# either val2 or val3 can be True:
com = df.filter(['val2', 'val3']).sum(1).ge(1)

           # val2 is the leftmost, so start with that
(df.assign(**df.filter(['val1', 'val3']).mask(df.val2, False))
           # next is the combination of val2 and val3
   .assign(val1 = lambda df: df.val1.mask(com, False), 
           val4 = lambda df: df.val4.mask(df.val5, False))
)
Out[84]: 
        val5   val2   val3   val1   val4   val6
index                                          
1       True  False   True  False  False  False
2      False   True  False  False   True  False
3      False  False  False   True  False   True

请注意,val6 未更改,因此值保持不变。

【讨论】:

    【解决方案2】:

    这是我尝试转换为字典时的结果:

    def section_filter(df, section_dict):
        result = {}
        for index, vals in df.to_dict('index').items():
            lst = []
            for val in section_dict.values():
                lst.append({k:v for k, v in vals.items() if k in val})
            for k, v in vals.items():
                if k not in [m for mi in section_dict.values() for m in mi]:
                    lst.append({k: v})
            for l in lst:
                for i in l:
                    if l[i]:
                        l.update({k:False for k in l.keys()})
                        l[i] = True
                        break 
            result[index] = {k: v for d in lst for k, v in d.items()}
        return pd.DataFrame.from_dict(result, orient='index', columns=df.columns)
    
    print(df)
    print()
    print(section_filter(df, val_dict))
    
            val5   val2   val3   val1   val4   val6
    index                                          
    1       True  False   True   True   True  False
    2      False   True   True  False   True  False
    3      False  False  False   True  False   True
    
        val5   val2   val3   val1   val4   val6
    1   True  False   True  False  False  False
    2  False   True  False  False   True  False
    3  False  False  False   True  False   True
    

    【讨论】:

    • 效率如何?三层嵌套for循环是我问的原因,除非你的实际数据不大
    • 数据相当小,但老实说它非常丑陋且效率不高。我正在尝试扩展它,因为实际的数据框有更多的 culumns 并且字典更长
    猜你喜欢
    • 2018-08-18
    • 2018-12-30
    • 2020-04-28
    • 2020-08-03
    • 2021-02-27
    • 2011-05-22
    • 1970-01-01
    • 1970-01-01
    • 2021-03-24
    相关资源
    最近更新 更多