Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Pandas:获取给定列的唯一行,但以其他列的某些条件为条件_Python_Pandas - Fatal编程技术网

Python Pandas:获取给定列的唯一行,但以其他列的某些条件为条件

Python Pandas:获取给定列的唯一行,但以其他列的某些条件为条件,python,pandas,Python,Pandas,我正在使用python 2.7。根据给定数据,如下所示: 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'],

我正在使用python 2.7。根据给定数据,如下所示:

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     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
我希望在dataframe中获得具有唯一id的输出,该输出符合以下条件:对于给定id

 '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     status     value     count
001     air        17        3
002    ground       8        2
003    ground      -3        3
004    unknown      0        1
005    ground       6        1

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

一个选项是将状态列的类型更改为类别,并根据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'
,您可以传递该函数。

一个选项是将状态列的类型更改为category,并根据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'
,您可以传递该函数。

您想在id上使用
groupby
。这对于值和计数来说很容易,但对于状态来说更复杂。我们需要编写自己的函数,它接受一个系列并返回一个属性

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非常优雅的回答中所述


如果您希望合并更高级的groupby功能,
group\u status()
函数确实为您奠定了基础。

您希望在id上使用
groupby
。这对于值和计数来说很容易,但是对于状态来说更复杂。我们需要编写自己的函数,它接受一个系列并返回一个属性

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\u status()
函数确实为您加入更高级的groupby功能奠定了基础。

分类列不是按字母顺序排序的,而是按传递给
.astype
的顺序排序的。所以如果你把它改成['ground','air','unknown',],ground将是第一个值,如果它存在的话。我不知道。知道这一点当然很有用。我读的是“你的例子是有序的”,忽略了第一行代码。我将稍微编辑一下我的答案。分类列不是按字母顺序排列的,而是按传递给
.astype
的顺序排列的。所以如果你把它改成['ground','air','unknown',],ground将是第一个值,如果它存在的话。我不知道。知道这一点当然很有用。我读的是“你的例子是有序的”,忽略了第一行代码。我将略加修改我的答案。