【问题标题】:Using groupby and filters on a dataframe在数据框上使用 groupby 和过滤器
【发布时间】:2020-12-08 14:22:22
【问题描述】:

我有一个包含字符串和整数值的数据框。

附加示例数据字典以了解我拥有的数据框:

data = {
'col1': ['A','A','A','B','B','B','C','C','C','D','D','D'],
'col2': [10,20,30,10,20,30,10,20,30,10,20,30],
'col3': ['X','X','X','X','Y','X','X','X','Y','Y','X','X'],
'col4': [45,23,78,56,12,34,87,54,43,89,43,12]
'col5': [3,4,6,4,3,2,4,3,5,3,4,6]
}

我需要提取数据如下:

  • col4 的最大值
  • 按 col1 分组
  • 如果值为 Y,则从结果中过滤掉 col3
  • 从结果中过滤 col5 以仅显示不超过 5 的值。

所以我尝试了一些方法并遇到了以下问题。

1- 我使用以下方法从数据中找到最大值。但我无法从每个组中找到最大值。

print(dataframe['col4'].max()) #this worked to get one max value
print(dataframe.groupby('col1').max() #this doesn't work

第二个对我不起作用,因为它也会返回 col2 的最大值。我需要结果对每个组下的最大行有 col2 值。

2- 我无法在一个命令中同时对 col3 (str) 和 col5 (int) 应用过滤器。有什么办法吗?

print(dataframe[dataframe['col3'] != 'Y' & dataframe['col5'] < 6]) #generates an error

我期望的输出是:

    col1  col2 col3  col4  col5
0     A    10    X    45     3
3     B    10    X    56     4
6     C    10    X    87     4
10    D    20    X    43     4
#
# 78 is max in group A, but ignored as col5 is 6 (we need < 6)
# Similarly, 89 is max in group D, but ignored as col3 is Y.

如果我做错了什么,我深表歉意。我对此很陌生。

谢谢。

【问题讨论】:

    标签: python-3.x dataframe pandas-groupby data-filtering


    【解决方案1】:

    我不是 python 开发人员,但我认为你这样做是错误的。 你应该有一个列表结构的结构列表。 然后你就可以开始处理这样的列表了。

    这是一个示例解决方案,因此可能会以更简单的方式完成:

    data = {
    'col1': ['A','A','A','B','B','B','C','C','C','D','D','D'],
    'col2': [10,20,30,10,20,30,10,20,30,10,20,30],
    'col3': ['X','X','X','X','Y','X','X','X','Y','Y','X','X'],
    'col4': [45,23,78,56,12,34,87,54,43,89,43,12],
    'col5': [3,4,6,4,3,2,4,3,5,3,4,6]
    }
    
    newData = [];
    
    for i in range(len(data['col1'])):
        newData.append({'col1' : data['col1'][i], 'col2' : data['col2'][i], 'col3' : data['col3'][i], 'col4' : data['col4'][i], 'col5' : data['col5'][i]})
    
    withoutY = list(filter(lambda d: d['col3'] != 'Y', newData))
    lessThen5 = list(filter(lambda d: d['col5'] < 5, withoutY))
    values = set(map(lambda d: d['col1'], lessThen5))
    groupped = [[d1 for d1 in lessThen5 if d1['col1']==d2] for d2 in values]
    
    result = [];
    for i in range(len(groupped)):
        result.append(max(groupped[i], key = lambda g: g['col4']))
    
    sortedResult = sorted(result, key = lambda r: r['col1'])
    
    print (sortedResult)
    

    结果:

    [
    {'col1': 'A', 'col2': 10, 'col3': 'X', 'col4': 45, 'col5': 3}, 
    {'col1': 'B', 'col2': 10, 'col3': 'X', 'col4': 56, 'col5': 4}, 
    {'col1': 'C', 'col2': 10, 'col3': 'X', 'col4': 87, 'col5': 4}, 
    {'col1': 'D', 'col2': 20, 'col3': 'X', 'col4': 43, 'col5': 4}
    ]
    

    【讨论】:

    • 嗨@Grzegorz我没有问题中提到的dict格式的数据。我只是分享了这个,以便其他人可以获取数据并使用它来分析我的问题。我有熊猫数据框格式的数据,需要从中找出解决方案。
    【解决方案2】:

    好吧,我实际上没有注意到。 所以我尝试了这样的事情:

    #fd is a filtered data
    fd=data.query('col3 != "Y"').query('col5 < 6')
    # or fd=data[data.col3 != 'Y'][data.col5 < 6]
    #m is max for col4 grouped by col1
    m=fd.groupby('col1')['col4'].max()
    

    这将按 col1 分组并从 col4 获取最大值,但结果我们有 2 个列(col1 和 col4)。 我不知道你想达到什么目的。 如果你想拥有所有线路,这里是代码:

    result=fd[lambda x: x.col4 == m.get(x.col1).values]
    

    您需要小心,因为“col1”并不总是只有一行。 例如。对于数据

    data = pd.DataFrame({
        'col1': ['A','A','A','A','B','B','B','B','C','C','C','D','D','D'],
        'col2': [20,10,20,30,10,20,20,30,10,20,30,10,20,30],
        'col3': ['X','X','X','X','X','X','Y','X','X','X','Y','Y','X','X'],
        'col4': [45,45,23,78,45,56,12,34,87,54,43,89,43,12],
        'col5': [1,3,4,6,1,4,3,2,4,3,5,3,4,6]})
    

    结果将是:

       col1  col2 col3  col4  col5
    0     A    20    X    45     1
    1     A    10    X    45     3
    5     B    20    X    56     4
    8     C    10    X    87     4
    12    D    20    X    43     4
    

    此外,如果您想使用普通索引而不是 ...、8、9 12,您可以使用“where”而不是“query”

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-16
      • 2021-01-22
      • 1970-01-01
      • 1970-01-01
      • 2017-01-09
      • 2017-05-18
      • 2019-03-29
      • 1970-01-01
      相关资源
      最近更新 更多