【问题标题】:Convert nested DataFrame with sorted unique values, to a nested Dictionary in Python将具有排序唯一值的嵌套 DataFrame 转换为 Python 中的嵌套字典
【发布时间】:2019-06-10 07:08:24
【问题描述】:

我正在尝试使用嵌套的 DataFrame 并将其转换为嵌套的字典。

这是我的原始 DataFrame,具有以下唯一值:

输入:df.head(5)

输出:

    reviewerName                                  title    reviewerRatings
0        Charles       Harry Potter Book Seven News:...                3.0
1      Katherine       Harry Potter Boxed Set, Books...                5.0
2           Lora       Harry Potter and the Sorcerer...                5.0
3           Cait       Harry Potter and the Half-Blo...                5.0
4          Diane       Harry Potter and the Order of...                5.0

输入:len(df['reviewerName'].unique())

输出:66130

鉴于 66130 个 unqiue 值中的每一个都有多个值(即“Charles”会出现 3 次),我将 66130 个唯一的“reviewerName”分配为 key在新的嵌套 DataFrame 中,然后使用“title”和“reviewerRatings”分配 value 作为同一嵌套 DataFrame 中的另一层 key:value。

输入:df = df.set_index(['reviewerName', 'title']).sort_index()

输出:

                                                       reviewerRatings
    reviewerName                               title
         Charles    Harry Potter Book Seven News:...               3.0
                    Harry Potter and the Half-Blo...               3.5
                    Harry Potter and the Order of...               4.0
       Katherine    Harry Potter Boxed Set, Books...               5.0
                    Harry Potter and the Half-Blo...               2.5
                    Harry Potter and the Order of...               5.0
...
230898 rows x 1 columns

作为后续行动 first question,我尝试将嵌套的 DataFrame 转换为嵌套的 Dictionary。

上面新的嵌套 DataFrame 列索引在第一行(第 3 列)显示“reviewerRatings”,在第二行(第 1 和 2 列)显示“reviewerName”和“title”,当我运行 df.to_dict() 方法时下面,输出显示{reviewerRatingsIndexName: {(reviewerName, title): reviewerRatings}}

输入:df.to_dict()

输出:

{'reviewerRatings': 
 {
  ('Charles', 'Harry Potter Book Seven News:...'): 3.0, 
  ('Charles', 'Harry Potter and the Half-Blo...'): 3.5, 
  ('Charles', 'Harry Potter and the Order of...'): 4.0,   
  ('Katherine', 'Harry Potter Boxed Set, Books...'): 5.0, 
  ('Katherine', 'Harry Potter and the Half-Blo...'): 2.5, 
  ('Katherine', 'Harry Potter and the Order of...'): 5.0,
 ...}
}

但对于下面我想要的输出,我希望得到我的输出为 {reviewerName: {title: reviewerRating}},这正是我在嵌套 DataFrame 中排序的方式。

{'Charles': 
 {'Harry Potter Book Seven News:...': 3.0, 
  'Harry Potter and the Half-Blo...': 3.5, 
  'Harry Potter and the Order of...': 4.0},   
 'Katherine':
 {'Harry Potter Boxed Set, Books...': 5.0, 
  'Harry Potter and the Half-Blo...': 2.5, 
  'Harry Potter and the Order of...': 5.0},
...}

有什么方法可以操作嵌套的 DataFrame 或嵌套的 Dictionary,这样当我运行 df.to_dict() 方法时,它会显示 {reviewerName: {title: reviewerRating}}

谢谢!

【问题讨论】:

    标签: python pandas dictionary dataframe nested


    【解决方案1】:

    groupbydictionariesreviewerName的lambda函数一起使用,然后输出Seriesto_dict转换:

    print (df)
      reviewerName                             title  reviewerRatings
    0      Charles  Harry Potter Book Seven News:...              3.0
    1      Charles  Harry Potter Boxed Set, Books...              5.0
    2      Charles  Harry Potter and the Sorcerer...              5.0
    3    Katherine  Harry Potter and the Half-Blo...              5.0
    4    Katherine   Harry otter and the Order of...              5.0
    

    d = (df.groupby('reviewerName')['title','reviewerRatings']
           .apply(lambda x: dict(x.values))
           .to_dict())
    print (d)
    
    {
        'Charles': {
            'Harry Potter Book Seven News:...': 3.0,
            'Harry Potter Boxed Set, Books...': 5.0,
            'Harry Potter and the Sorcerer...': 5.0
        },
        'Katherine': {
            'Harry Potter and the Half-Blo...': 5.0,
            'Harry otter and the Order of...': 5.0
        }
    }
    

    【讨论】:

      【解决方案2】:

      有几种方法。您可以使用groupbyto_dict,或使用collections.defaultdict 迭代行。值得注意的是,后者并非必然效率较低。

      groupby + to_dict

      从每个groupby 对象构造一个系列并将其转换为字典以给出一系列字典值。最后,通过另一个 to_dict 调用将其转换为字典字典。

      res = df.groupby('reviewerName')\
              .apply(lambda x: x.set_index('title')['reviewerRatings'].to_dict())\
              .to_dict()
      

      collections.defaultdict

      定义 defaultdictdict 对象并逐行迭代您的数据帧。

      from collections import defaultdict
      
      res = defaultdict(dict)
      for row in df.itertuples(index=False):
          res[row.reviewerName][row.title] = row.reviewerRatings
      

      生成的defaultdict 不需要转换回常规的dict,因为defaultdictdict 的子类。

      性能基准测试

      基准测试取决于设置和数据。您应该使用自己的数据进行测试,看看哪种方法最有效。

      # Python 3.6.5, Pandas 0.19.2
      
      from collections import defaultdict
      from random import sample
      
      # construct sample dataframe
      np.random.seed(0)
      n = 10**4  # number of rows
      names = np.random.choice(['Charles', 'Lora', 'Katherine', 'Matthew',
                                'Mark', 'Luke', 'John'], n)
      books = [f'Book_{i}' for i in sample(range(10**5), n)]
      ratings = np.random.randint(0, 6, n)
      
      df = pd.DataFrame({'reviewerName': names, 'title': books, 'reviewerRatings': ratings})
      
      def jez(df):
          return df.groupby('reviewerName')['title','reviewerRatings']\
                   .apply(lambda x: dict(x.values))\
                   .to_dict()
      
      def jpp1(df):
          return df.groupby('reviewerName')\
                   .apply(lambda x: x.set_index('title')['reviewerRatings'].to_dict())\
                   .to_dict()
      
      def jpp2(df):
          dd = defaultdict(dict)
          for row in df.itertuples(index=False):
              dd[row.reviewerName][row.title] = row.reviewerRatings
          return dd
      
      %timeit jez(df)   # 33.5 ms per loop
      %timeit jpp1(df)  # 17 ms per loop
      %timeit jpp2(df)  # 21.1 ms per loop
      

      【讨论】:

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