A few things...
First, typically don't reset the index of the pipeline in an algorithm. The index is the list of securities. The reason you maybe did this in a notebook is because the pipeline dataframe returned there has a multi index (indexed by security AND day). In an algorithm the index is a simple index (indexed by security only). An easy way to make a simple index dataframe within a notebook and make it look like an algorithm dataframe, is to use the '.xs' method (see http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.xs.html). All in one step. No need to reset indexes etc.
# Run the pipeline across several days
results = run_pipeline(pipe, '2016-07-08', '2016-08-08')
# Use the '.xs' method to get a single days slice of the dataframe (in this case '2016-07-08')
# This new dataframe looks like the one returned when using pipeline in algorithms
single_day_results = results.xs('2016-07-08')
Second, I'd use the '.groupby' and '.apply' methods to calculate the means. This does the job in a single line (and a small function). Everyone has their preference, and this is just one approach.
context.output = pipeline_output('my_pipeline')
# Helper function to get the sector means - used below
grp['sector_mean'] = grp['gross_margin'].mean()
# The following adds a column called 'sector_mean' to the pipe output
context.output = context.output.groupby('sector_code').apply(_sector_mean)
Finally, while it's often helpful to add columns to an existing pipe output, in this specific case it's probably not needed. Take a look at the '.demean' method (see the docs https://www.quantopian.com/help#quantopian_pipeline_factors_Factor ). Used in conjunction with the 'groupby' parameter this gets you, I believe, exactly what you want all within the pipeline definition.
Q500 = Q500US()
Energy = morningstar.asset_classification.morningstar_sector_code.latest != 309.0
Mining = morningstar.asset_classification.morningstar_sector_code.latest != 101.0
sector = morningstar.asset_classification.morningstar_sector_code.latest
tradeable_stocks = (
gross_margin = morningstar.operation_ratios.gross_margin.latest
gross_margin_demeaned = gross_margin.demean(groupby = sector)
screen = tradeable_stocks)
Then, to get the stocks where the gross margin is greater than the sector mean, all you need to do is check for 'gross_margin_demeaned >0'.
# Below is how to get the securities which are greater than the mean for it's sector
# using the pipeline method 'demean' and not needing to calculate and add
# the 'sector_mean' column
context.security_list_demean = (context.output
.query('gross_margin_demeaned > 0')
Attached is an algorithm which includes both methods and logs the results. Note the two logs are the same.