【问题标题】:Utilizing nested dictionary to replace specific values in a Pandas Dataframe利用嵌套字典替换 Pandas Dataframe 中的特定值
【发布时间】:2022-01-20 19:17:55
【问题描述】:

我有一个 pandas 数据框,我需要用嵌套字典中的相应数字替换所有“是”值。嵌套字典由“Store”列的行值作为外部键组成。内部键是名为“A”和“B”的列。

这是数据框:

import pandas as pd

data = [['abc', 'jan','yes','no'], ['abc', 'feb','no','yes'], ['def', 'jan', 'yes','yes'],  ['def', 'feb', 'no','yes']]

df = pd.DataFrame(data, columns = ['Store', 'Month', 'A','B' ])

df
 
  Store Month    A    B
0   abc   jan  yes   no
1   abc   feb   no  yes
2   def   jan  yes  yes
3   def   feb   no  yes

这是嵌套字典:

# dict = {row value in 'Store' column:{column:point value}}
dict = {'abc':{'A':5,'B':4},'def':{'A':3,'B':2}}

这是所需的输出:

  Store Month    A    B
0   abc   jan    5   no
1   abc   feb   no    4
2   def   jan    3    2
3   def   feb   no    2

【问题讨论】:

    标签: python pandas dataframe dictionary


    【解决方案1】:

    'yes' 替换为np.nan,将fillna 替换为嵌套字典的值:

    d = {'abc':{'A':5,'B':4},'def':{'A':3,'B':2}}
    out = df.replace({'yes': np.nan}).groupby('Store') \
            .apply(lambda x: x.fillna(d[x.name])).droplevel(0)
    print(out)
    
    # Output
      Store Month   A   B
    0   abc   jan   5  no
    1   abc   feb  no   4
    2   def   jan   3   2
    3   def   feb  no   2
    

    【讨论】:

      【解决方案2】:

      试试这个:

      def find_num(store, col_value, col_name):
          if col_value == "yes":
              sub_dict = dict[store]
              return sub_dict[col_name]
          else:
              return "no"
      
      
      for col in list(df.columns):
          if col == "Store" or col == "Month":
              continue
          df[col] = df.apply(lambda x: find_num(x['Store'], x[col], col), axis=1)
      
      print(df)
      

      【讨论】:

        【解决方案3】:

        这是另一个使用 np.where 的选项。

        (i) map dict(仅供参考,dict 是字典构造函数的名称,我在此处将其替换为 dct)到“存储”以匹配每一行的相关字典。

        (ii) 将df[['A','B']] 展平为一个 numpy 数组

        (iii) 迭代 (i) 的结果并获取每个字典的值,并使用 itertools.chain 展平结果列表

        (iv) 使用np.where 根据 (ii) 的结果是否为“是”来选择值

        (v) 将 (iv) 的结果重新整形为二维数组并分配回df[['A','B']]

        from itertools import chain
        mapper = df['Store'].map(dct)
        flat_AB = df[['A','B']].to_numpy().flatten()
        values_from_dict = list(chain.from_iterable([d.values() for d in mapper]))
        df[['A','B']] = np.where(flat_AB == 'yes', values_from_dict, flat_AB).reshape(-1,2)
        

        或者你可以直接使用DataFrame本身(但我认为这比上面的方法慢)

        df[['A','B']] = np.where(df[['A','B']] == 'yes', pd.DataFrame(df['Store'].map(dct).tolist()), df[['A','B']])
        

        输出:

          Store Month   A   B
        0   abc   jan   5  no
        1   abc   feb  no   4
        2   def   jan   3   2
        3   def   feb  no   2
        

        【讨论】:

          猜你喜欢
          • 2018-11-01
          • 1970-01-01
          • 2013-11-16
          • 2019-04-08
          • 2023-02-10
          • 2022-01-01
          • 2022-01-02
          • 1970-01-01
          相关资源
          最近更新 更多