Pandas:获取给定列的唯一行,但取决于其他列的某些条件

时间:2016-10-05 14:15:09

标签: python pandas

我正在使用python 2.7。从给定的数据如下:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#" class="test">test 1</a>
<a href="#" class="test">test 2</a>
<a href="#" class="test">test 3</a>
<a href="#" class="test">test 4</a>

数据如下所示:

data = pd.DataFrame({'id':['001','001','001','002','002','003','003','003','004','005'],
                   'status':['ground','unknown','air','ground','unknown','ground','unknown','unknown','unknown','ground'],
                   'value':[10,-5,12,20,-12,2,-4,-1,0,6]})

我想获取数据帧中具有唯一ID的输出,条件符合以下条件:对于给定的id

id     status     value
001    ground       10
001    unknown      -5
001    air          12
002    ground       20
002    unknown     -12
003    ground        2
003    unknown      -4
003    unknown      -1
004    unknown       0
005    ground        6

因此,预期输出如下。

 'status': If 'air' does exist, pick 'air'.
           If 'air' does not exist, pick 'ground'.  
           If both 'air' and 'ground' do not exist, pick 'unknown'.

 'value': Sum of values for each id
 'count': Count the number of rows for each id

我可以为每个唯一ID进行循环,但它不够优雅,计算也很昂贵,尤其是当数据变大时。我是否知道更好的pythonic风格和更有效的方式来提出这个输出?提前谢谢。

2 个答案:

答案 0 :(得分:2)

一个选项是将状态列的类型更改为类别,并根据groupby.agg中的类型进行排序:

df['status'] = df['status'].astype('category', categories=['air', 'ground', 'unknown'], ordered=True)

df.sort_values('status').groupby('id').agg({'status': 'first', 'value': ['sum', 'count']})
Out: 
      status value      
       first   sum count
id                      
001      air    17     3
002   ground     8     2
003   ground    -3     3
004  unknown     0     1
005   ground     6     1

此处,由于值按'air''ground''unknown'顺序排序,'first'会返回正确的值。如果您不想更改类型,可以定义自己的函数,返回air / ground / unknown而不是'first',您可以传递该函数。

答案 1 :(得分:2)

您想在ID上使用groupby。这很容易获得价值和数量,但对于状态来说比较棘手。我们需要编写自己的函数,它接受一个pandas Series并返回一个属性。

def group_status(x):
    if (x=='air').any():
        y = 'air'
    elif (x=='ground').any():
        y = 'ground'
    else:
        y = 'unknown'
    return y

data = data.groupby(by='id').agg({'value': ['sum', 'count'], 'status': [group_status]})
data.columns = ['status', 'value', 'count']

print(data)

     status  value  count
id          
001  air      17     3
002  ground   8      2
003  ground   -3     3
004  unknown  0      1
005  ground   6      1

在这里,我们确保保留空气,地面,未知顺序,而无需将列类型更改为分类,如ayhan非常优雅的答案所述。

如果您希望合并更高级的群组功能,group_status()功能确实奠定了基础。