Pandas 基于数据帧行的聚合计数排除数据帧的列

Pandas 基于数据帧行的聚合计数排除数据帧的列,pandas,dataframe,Pandas,Dataframe,我有以下数据帧: Fruit John Mary Paul Anna Apples 1 1 1 5 Oranges 2 2 2 3 Lemons 1 1 4 1 Berr

我有以下数据帧:

   Fruit                John      Mary        Paul     Anna
   Apples                1         1            1       5
   Oranges               2         2            2       3
   Lemons                1         1            4       1
   Berries               2         2            2       7
我还有以下嵌套字典:

{Apples:{5:1,1:3},Oranges:{3:1,2:3},Lemons:{4:1,1:3},Berries:{7:1,2:3}}
这告诉我

  • 1人有5个苹果,3人有1个苹果
  • 1人有3个桔子,3人有2个桔子
  • 1人有4个柠檬,3人有1个柠檬
  • 1人有7个浆果,3人有2个浆果
  • 我现在需要的是提取那些要么有5个苹果,要么有3个桔子,要么有4个柠檬,要么有7个浆果的人,也就是说,上面字典中所有的特殊情况

    这意味着,由于玛丽在《无果》中是唯一的一个人,但总是在3个相同的类别中,因此将被排除在外

    我可以通过一系列复杂且性能不佳的for循环来实现这一点,但我想知道是否有更有效的方法来实现这一点

    预期输出:

       Fruit           Paul     Anna
       Apples            2       5
       Oranges           2       3
       Lemons            4       1
       Berries           2       7
    

    您可以将水果指定为dataframe的索引,对于水果的条件,您可以提取列名

            John    Mary    Paul    Anna
    Fruit               
    Apples  3   1   2   5
    Oranges 2   2   2   3
    Lemons  1   1   4   1
    Berries 2   2   2   7
    
    df.set_index(['Fruit'],inplace=True)
    column_names = df.apply(lambda x:x.name  if ((x.loc['Apples']==5) | (x.loc['Oranges']==3) | (x.loc['Lemons']==4) | (x.loc['Berries']==7)) else None)
    df[list(filter(None,column_names))]
    
    输出:


    您可以将水果指定为dataframe的索引,对于水果的条件,您可以提取列名

            John    Mary    Paul    Anna
    Fruit               
    Apples  3   1   2   5
    Oranges 2   2   2   3
    Lemons  1   1   4   1
    Berries 2   2   2   7
    
    df.set_index(['Fruit'],inplace=True)
    column_names = df.apply(lambda x:x.name  if ((x.loc['Apples']==5) | (x.loc['Oranges']==3) | (x.loc['Lemons']==4) | (x.loc['Berries']==7)) else None)
    df[list(filter(None,column_names))]
    
    输出:


    假设嵌套字典实际上不是该过程的重要组成部分,并且您只想确定哪一个人对应于任何行中的唯一值,我们可以执行以下操作:

    from io import StringIO
    
    import pandas as pd
    
    
    data = StringIO('''Fruit                John      Mary        Paul     Anna
    Apples                1         1            1       5
    Oranges               2         2            2       3
    Lemons                1         1            4       1
    Berries               2         2            2       7''')
    
    df = pd.read_csv(data, sep='\s+').set_index('Fruit')
    
    tr = df.transpose()
    mask = ~pd.DataFrame({c: tr.duplicated(c, keep=False) for c in tr.columns}).all(axis=1)
    
    df = df[mask.index[mask]]
    
    我们将索引设置为
    'Fruit'
    ,然后进行转置,每个
    'Fruit'
    得到一列,每个人得到一行。然后,我们创建一个掩码,用于确定列中的值是否与任何其他值重复,并检查在所有情况下是否为真。然后,我们可以使用这个掩码过滤原始数据帧中的列

    这为我们提供了以下信息,如
    df

             Paul  Anna
    Fruit              
    Apples      1     5
    Oranges     2     3
    Lemons      4     1
    Berries     2     7
    

    假设嵌套字典实际上不是该过程的重要组成部分,并且您只想确定哪一个人对应于任何行中的唯一值,我们可以执行以下操作:

    from io import StringIO
    
    import pandas as pd
    
    
    data = StringIO('''Fruit                John      Mary        Paul     Anna
    Apples                1         1            1       5
    Oranges               2         2            2       3
    Lemons                1         1            4       1
    Berries               2         2            2       7''')
    
    df = pd.read_csv(data, sep='\s+').set_index('Fruit')
    
    tr = df.transpose()
    mask = ~pd.DataFrame({c: tr.duplicated(c, keep=False) for c in tr.columns}).all(axis=1)
    
    df = df[mask.index[mask]]
    
    我们将索引设置为
    'Fruit'
    ,然后进行转置,每个
    'Fruit'
    得到一列,每个人得到一行。然后,我们创建一个掩码,用于确定列中的值是否与任何其他值重复,并检查在所有情况下是否为真。然后,我们可以使用这个掩码过滤原始数据帧中的列

    这为我们提供了以下信息,如
    df

             Paul  Anna
    Fruit              
    Apples      1     5
    Oranges     2     3
    Lemons      4     1
    Berries     2     7
    

    您还可以使用dict中的
    isin

    d = {'Apples':{5:1,1:3},'Oranges':{3:1,2:3},'Lemons':{4:1,1:3},'Berries':{7:1,2:3}}
    
    将上述dict键转换为
    df

    # df1 = pd.DataFrame([[k for k in j.keys()] for i, j in d.items()])
    
    df1 = pd.DataFrame(list(zip(*list(d.values())))).T
    
    df[df.isin(df1[0])].dropna(how='all', axis=1).fillna(df).set_index(df.Fruit)
    
    # Output:
    
             Paul   Anna
    Fruit       
    Apples   1.0    5.0
    Oranges  2.0    3.0
    Lemons   4.0    1.0
    Berries  2.0    7.0
    

    您还可以使用dict中的
    isin

    d = {'Apples':{5:1,1:3},'Oranges':{3:1,2:3},'Lemons':{4:1,1:3},'Berries':{7:1,2:3}}
    
    将上述dict键转换为
    df

    # df1 = pd.DataFrame([[k for k in j.keys()] for i, j in d.items()])
    
    df1 = pd.DataFrame(list(zip(*list(d.values())))).T
    
    df[df.isin(df1[0])].dropna(how='all', axis=1).fillna(df).set_index(df.Fruit)
    
    # Output:
    
             Paul   Anna
    Fruit       
    Apples   1.0    5.0
    Oranges  2.0    3.0
    Lemons   4.0    1.0
    Berries  2.0    7.0
    

    预期产量是多少?最终数据帧的外观如何?使用预期输出进行了更新Paul不应该有
    0
    /
    None
    苹果吗?根据您的问题,预期输出是什么?最终数据帧的外观如何?使用预期输出进行了更新Paul在回答您的问题时不应该有
    0
    /
    None
    苹果吗?谢谢,如果我想在列上自动评分(无需在apply函数的or条件下输入)?我这样问是因为在我的例子中,我有30000个这样的列,我不能硬编码所有的列。是的,你可以迭代。即使您有30000列,该解决方案也能完美工作。但是如果您有30000个条件,我们可能需要在“lambda”函数中输入条件:-)。谢谢,如果我想在列上自动写入条件(无需在apply函数的or条件中输入条件)?我这样问是因为在我的例子中,我有30000个这样的列,我不能硬编码所有的列。是的,你可以迭代。即使您有30000列,该解决方案也能完美工作。但是如果你有30000个条件,我们可能需要把条件放在“lambda”函数中:-)。
    df1=df.from_dict({i:{y:x代表x,y代表j.items()}代表i,j代表d.items()})。T
    只取计数为1的第一个实例。例如,如果我的dictionary
    d={Key1:{5:1,6:1}}
    中有两个值,那么它只会在第1列中返回5,而不会在第1列中同时返回5和6(该列包含1个计数的所有值)@user37143在这种情况下,使用列表理解从dictionary获取所有值。我会更新答案。它现在应该可以处理重复的值。@user37143乐于帮助:)
    df1=df.from_dict({i:{y:x代表x,y代表j.items()}代表i,j代表d.items()})。T
    只接受计数为1的第一个实例。例如,如果我的dictionary
    d={Key1:{5:1,6:1}}
    中有两个值,那么它只会在第1列中返回5,而不会在第1列中同时返回5和6(该列包含1个计数的所有值)@user37143在这种情况下,使用列表理解从dictionary获取所有值。我会更新答案。它现在应该可以使用重复的值。@user37143乐意帮助:)