title: Calculating weighted average using grouped .agg in pandas
body: <p>I would like to calculate, by group, the mean of one column and the weighted mean of another column in a dataset using the <code>.agg()</code> function within <strong>pandas</strong>. I am aware of a few solutions, but they aren't very concise. </p>
  
  <p>One solution has been posted here (<a href="https://stackoverflow.com/questions/46714555/pandas-and-groupby-how-to-calculate-weighted-averages-within-an-agg">pandas and groupby: how to calculate weighted averages within an agg</a>, but it still doesn't seem very flexible because the weights column is hard coded in the lambda function definition. I'm looking to create a syntax closer to this: </p>
  
  <pre><code>(
  df
  .groupby(['group'])
  .agg(avg_x=('x', 'mean'),
       wt_avg_y=('y', 'weighted_mean', weights='weight')
  )
  </code></pre>
  
  <p>Here is a fully worked example with code that seems needlessly complicated:</p>
  
  <pre><code>import pandas as pd
  import numpy as np
  
  # sample dataset
  df = pd.DataFrame({
      'group': ['a', 'a', 'b', 'b'],
      'x': [1, 2, 3, 4],
      'y': [5, 6, 7, 8],
      'weights': [0.75, 0.25, 0.75, 0.25]
  })
  df
  #&gt;&gt;&gt;    group   x   y   weights
  #&gt;&gt;&gt; 0      a   1   5   0.75
  #&gt;&gt;&gt; 1      a   2   6   0.25
  #&gt;&gt;&gt; 2      b   3   7   0.75
  #&gt;&gt;&gt; 3      b   4   8   0.25
  
  # aggregation logic
  summary = pd.concat(
      [
          df.groupby(['group']).x.mean(),
          df.groupby(['group']).apply(lambda x: np.average(x['y'], weights=x['weights']))
      ], axis=1
  )
  # manipulation to format the output of the aggregation
  summary = summary.reset_index().rename(columns={'x': 'avg_x', 0: 'wt_avg_y'})
  
  # final output
  summary
  #&gt;&gt;&gt;    group   avg_x   wt_avg_y
  #&gt;&gt;&gt; 0      a   1.50    5.25
  #&gt;&gt;&gt; 1      b   3.50    7.25
  </code></pre>