查找组中

时间:2016-03-02 14:15:13

标签: python pandas

我有这个数据框的条目是:

In [77]: df.loc[1]
Out[77]: 
img            410T1_B03_S06_W2_cell1_ann.tif
immean                                   1302
imvar                                  101773
imrange                                  2640
imtotalvar                              63321
method                            maxminratio
thresh                                   1.01
cont                                        8
minz                                        2
cent                                       50
zs                                          1
localmax                                    F
sha                                      1383
tp                                          3
fp                                         44
fn                                          0
time                                    139.4
precision                           0.0638298
sensitivity                                 1
score                                    0.12
Name: 1, dtype: object

使用dtypes:

In [79]: df.dtypes
Out[79]: 
img            category
immean            int64
imvar             int64
imrange           int64
imtotalvar        int64
method         category
thresh          float64
cont           category
minz           category
cent           category
zs             category
localmax       category
sha            category
tp              float64
fp              float64
fn              float64
time            float64
precision       float64
sensitivity     float64
score           float64
dtype: object

我需要按'method'对它们进行分组,然后按相同的['cont','minz','cent','zs','localmax','sha']对它们进行分组,一旦完成,请获取具有最佳'score'的行(同时保留其他行)的相关信息)。

我做了一些非常脏的代码,可以完成这项工作,但我想以正确的方式完成它:

def multiplecond(df,listvar,listvalues):
  res = df[listvar[0]]==listvalues[0]
  for var,val in zip(listvar[1:],listvalues[1:]):
    res = (res) & (df[var]==val)
  return res

falseparams = ['cont','minz','cent','zs','localmax','sha']
falseparamsvalues = [list(df[x].values.categories) for x in falseparams]
falseparamssets = [[a,b,c,d,e,f] for a in falseparamsvalues[0]
                                 for b in falseparamsvalues[1]
                                 for c in falseparamsvalues[2]
                                 for d in falseparamsvalues[3]
                                 for e in falseparamsvalues[4]
                                 for f in falseparamsvalues[5]]

spe = {}
for method in df.method.values.categories:
  for falseparamsset in falseparamssets:
    df2 = df[multiplecond(df,['method']+falseparams,[method]+falseparamsset)]
    if not df2.empty:
      n = method + '_'.join([''.join([str(x),str(y)]) for x,y in
                             zip(falseparams,falseparamsset)])
      spe[n]=df2.copy()

df2 = []
for d in spe:
  # get best score (=best thresh) for method
  g = spe[d].groupby('img')
  g = g['score'].max()
  df2 += [[d,g.mean()]]
  # visually verify thresh range

df2 = pd.DataFrame(df2,columns=['method','maxscore'])
df2.sort_values(by='score',ascending=False,inplace=True)

这样做的正确方法是什么?

编辑:这是我的数据框{200}的第一个条目的可用版本http://pastebin.com/r5uAiyHU

EDIT2:感谢firelynx的回答,我设法做了一些不那么脏的事情。这是怎么回事:

gbyimgbymet=df.groupby(['img','method','minz','zst','minshape'])
idx = [list(a[1][a[1]['score']==a[1].score.max()].index) for a in gbyimgbymet]
a=[]
for i in idx:
  a+=i

bestscoresbyimgbymet = df.loc[a]

我知道可能会稍微好一些,特别是加入索引。 firelynx的回答并不真正适合的原因是我需要所有具有最大值的行,而不仅仅是一行,这是argmax返回的行。出于这个原因,我可能也不能使用agg方法。如果我错了,请纠正我。

1 个答案:

答案 0 :(得分:2)

好的,你的代码非常脏,我认为你的解决方案过度设计了,所以我只想给你一个例子,说明如何使用更简洁的示例代码来概念化。

我的示例数据框:

   a  b  c  othervalue
0  1  a  z         100
1  1  b  x         101
2  1  c  y         102
3  2  d  v         103
4  2  e  u         104
5  2  f  t         105

使用argmax,我们可以获得该组中最高值的索引。

df.groupby('a').agg({'othervalue':pd.Series.argmax})
   othervalue
a            
1           2
2           5

现在我们可以在.loc方法中使用该值来从原始数据帧中获取整行。

max_scores = df.groupby('a').agg({'othervalue':pd.Series.argmax})['othervalue']
df.loc[max_scores]
   a  b  c  othervalue
2  1  c  y         102
5  2  f  t         105

具有最大值的多行(问题扩展名)

如果你有多行符合最大值,你将需要做一些不同的事情,还有一步。

    a  b  c  othervalue
0   1  a  z         100
1   1  b  x         101
2   1  c  y         102
3   2  d  v         103
4   2  e  u         104
5   2  f  t         105
6   1  a  z         100
7   1  b  x         101
8   1  c  y         102
9   2  d  v         103
10  2  e  u         104
11  2  f  t         105

通过上面的例子,首先我们得到每个组中的最大值,并重置索引,以便我们可以将它用于即将到来的合并。

maxvalues_per_group = df.groupby('a').agg({'othervalue':pd.np.max})
maxvalues_per_group.reset_index(inplace=True)

使用这些值,我们再次合并原始数据框,以获得与每个组中的最大值匹配的所有行。

df.merge(on=['a', 'othervalue'], right=maxvalues_per_group, how='inner')

   a  b  c  othervalue
0  1  c  y         102
1  1  c  y         102
2  2  f  t         105
3  2  f  t         105