【问题标题】:Multiple modes for multiple accounts in PythonPython中多个帐户的多种模式
【发布时间】:2021-10-02 15:13:24
【问题描述】:

我有一个包含多个帐户的数据框,其中显示了不同模式的动物类别。如何识别具有多个模式的帐户?

例如,请注意账户 3 只有一种模式(即“狗”),但账户 1、2 和 4 有多种模式(即不止一种模式)。

test = pd.DataFrame({'account':[1,1,1,2,2,2,2,3,3,3,3,4,4,4,4],
             'category':['cat','dog','rabbit','cat','cat','dog','dog','dog','dog','dog','rabbit','rabbit','cat','cat','rabbit']})

我正在寻找的预期输出是这样的:

pd.DataFrame({'account':[1,2,4],'modes':[3,2,2]})

其次,我尝试为所有具有多种模式的帐户采用任何随机最高模式。我想出了以下代码,但是,这仅返回每个帐户的第一个(字母)模式。我的直觉告诉我可以在下面的iloc 括号内写一些东西,也许是一个介于 0 和模式总数之间的随机数组,但我无法完全做到。

test.groupby('account')['category'].agg(lambda x: x.mode(dropna=False).iloc[0])

有什么建议吗?非常感谢。

【问题讨论】:

  • 给定数据框的预期输出是什么?
  • 已更新,谢谢。
  • 是选择随机模式还是真的是次要问题?
  • 你删除了你的答案!我认为这是一个很好的。最终,我需要一个随机模式,因为我正在处理每次访问存在多个 ICD-10 代码,通常是相同类型(因此生成模式)。虽然它不是很常见(12% 的频率),但我想选择任何随机模式,而不是第一个字母模式,这样我的分类模型就不会偏向字母表的开头:p 那是很长的版本我的问题。感谢您的帮助!
  • @GabeVerzino 我未删除,但已删除,因为从措辞看来您想更多地关注确定哪些是重复的,我的回答并没有真正解决,但它确实成功返回一个随机模式,所以我会添加它,因为它很有用

标签: python pandas mode


【解决方案1】:

您可以为此使用 numpy.random.choice

test.groupby('account')['category'].agg(
    lambda x: np.random.choice(x.mode(dropna=False)))

【讨论】:

    【解决方案2】:

    不确定你想要什么,但你可以试试:

    out=test.groupby('account')['category'].apply(lambda x: x.mode(dropna=False).values)
    

    out的输出:

    account
    1    [cat, dog, rabbit]
    2            [cat, dog]
    3                 [dog]
    4         [cat, rabbit]
    Name: category, dtype: object
    

    对于随机模式值:

    from random import choice
    
    out=test.groupby('account')['category'].agg(
        lambda x: choice(x.mode(dropna=False)))
    

    out的输出(每次运行代码都会得到不同的输出):

    account
    1    rabbit
    2       dog
    3       dog
    4    rabbit
    Name: category, dtype: object
    

    对于您的预期输出用途:

    out=test.groupby('account')['category'].apply(lambda x: x.mode(dropna=False).count()).reset_index()
    out=out[out['category'].ne(1)]
    

    out的输出:

    account     category
    0   1       3
    1   2       2
    3   4       2
    

    【讨论】:

      【解决方案3】:

      因为在平局的情况下您只想要任意随机模式,您可以使用groupby + size。 (本质上是与@abw333's solution 非常相似的包装器)。这很好,因为它避免了任何groupby.apply,而是使用了内置的 groupby.size,它很快。

      我们在 groupby 中使用sort=False,因此生成的 Series 按组在原始 DataFrame 中出现的顺序排序。然后因为排序算法 'mergesort' 在 tie 的情况下是稳定的,这将确定性地返回在 tie 的情况下出现在 DataFrame 中的 first (前面的行)的模式。因此,如果您想获得 random 模式,您可以在应用此之前.sample(frac=1),以便它打乱所有行,然后返回该模式。

      def fast_mode(df, gp_cols, value_col):
          """ 
          Calculate the mode of a column, ignoring null values recognized by pandas. 
      
          If there is a tie for the mode, the modal value is the modal value that appears **first** in the
          DataFrame. 
      
          Parameters
          ----------
          df : pandas.DataFrame
              DataFrame over which to calcualate the mode. 
          gp_cols : list of str
              Columns to groupby for calculation of mode.
          value_col : str
              Column for which to calculate the mode. 
      
          Return
          ------ 
          pandas.DataFrame
              One row for the modal value per key_cols 
          """
      
          return ((df.groupby(gp_cols + [value_col], observed=True, sort=False).size() 
                     .to_frame('mode_counts').reset_index() 
                     .sort_values('mode_counts', ascending=False, kind='mergesort') 
                     .drop_duplicates(subset=gp_cols))
                   .reset_index(drop=True))
      

      # Will always return the same one that occurs first in DataFrame
      fast_mode(df, gp_cols=['account'], value_col='category')
      #   account category  mode_counts
      #0        3      dog            3
      #1        2      cat            2
      #2        4   rabbit            2
      #3        1      cat            1
      
      # Sampling allows you to select a "random one" in case of ties
      fast_mode(df.sample(frac=1, random_state=12), gp_cols=['account'], value_col='category')
      #   account category  mode_counts
      #0        3      dog            3
      #1        4      cat            2
      #2        2      dog            2
      #3        1      cat            1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-03-22
        • 1970-01-01
        • 1970-01-01
        • 2011-06-07
        • 2013-01-25
        • 1970-01-01
        相关资源
        最近更新 更多