Python Pandas group by function
<p>I have this table </p>

<pre><code>    uname   sid usage
0   Ahmad   a   5
1   Ahmad   a   7
2   Ahmad   a   10
3   Ahmad   b   2
4   Mohamad c   6
5   Mohamad c   7
6   Mohamad c   9
</code></pre>

<p>I want to group by uname and side, and have usage column =  <code>group.max</code> - <code>group.min</code>. But if group count is <code>1</code> return group <code>max</code> </p>

<p>the out put should be </p>

<pre><code>    uname   sid usage
0   Ahmad   a   5
1   Ahmad   b   2
2   Mohamad c   3    
</code></pre>

<p>You can use <a href="http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.groupby.html" rel="nofollow"><code>groupby</code></a> with <a href="http://pandas.pydata.org/pandas-docs/stable/generated/pandas.core.groupby.GroupBy.apply.html" rel="nofollow"><code>apply</code></a> difference <a href="http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.max.html" rel="nofollow"><code>max</code></a> and <a href="http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.min.html" rel="nofollow"><code>min</code></a> if <code>length</code> is more as <code>1</code> else <code>max</code>:</p>

<pre><code>df = df.groupby(['uname','sid'])['usage']
       .apply(lambda x: x.max()-x.min() if len(x) &gt; 1 else x.max())
       .reset_index()
print (df)
     uname sid  usage
0    Ahmad   a      5
1    Ahmad   b      2
2  Mohamad   c      3
</code></pre>

<p>I think instead <code>max</code> you can use <code>iloc</code> too:</p>

<pre><code>df = df.groupby(['uname','sid'])['usage']
       .apply(lambda x: x.max()-x.min() if len(x) &gt; 1 else x.iloc[0])
       .reset_index()
print (df)
     uname sid  usage
0    Ahmad   a      5
1    Ahmad   b      2
2  Mohamad   c      3
</code></pre>

<p>Another solution with <a href="http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.where.html" rel="nofollow"><code>Series.where</code></a>, which test <a href="http://pandas.pydata.org/pandas-docs/stable/generated/pandas.core.groupby.GroupBy.size.html" rel="nofollow"><code>size</code></a>:</p>

<pre><code>g = df.groupby(['uname','sid'])['usage']
s = g.max()-g.min()
print (s)
uname    sid
Ahmad    a      5
         b      0
Mohamad  c      3
Name: usage, dtype: int64

print (g.size() == 1)
uname    sid
Ahmad    a      False
         b       True
Mohamad  c      False
dtype: bool

print (s.where(g.size() != 1, g.max()).reset_index())
     uname sid  usage
0    Ahmad   a      5
1    Ahmad   b      2
2  Mohamad   c      3
</code></pre>

python pandas group-by max min