我有这个数据框的条目是:
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
方法。如果我错了,请纠正我。
答案 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