Pandas: resta la media de la fila de cada elemento en la fila

Tengo un dataframe con filas indexadas por tipo de elemento químico y columnas que representan diferentes muestras. Los valores son flotantes que representan el grado de presencia del elemento de fila en cada muestra.

Quiero calcular la media de cada fila y restarla de cada valor en esa fila específica para normalizar los datos y hacer un nuevo dataframe de ese conjunto de datos.

Intenté usar la media (1), que me dio un objeto de la serie con la media para cada elemento químico, lo cual es bueno, pero luego intenté usar la resta, que no funcionó.

Puede usar el método sub de DataFrame y especificar que la resta debe ocurrir en la fila ( axis=0 ) en lugar del comportamiento predeterminado en la columna:

 df.sub(df.mean(axis=1), axis=0) 

Aquí hay un ejemplo:

 >>> df = pd.DataFrame({'a': [1.5, 2.5], 'b': [0.25, 2.75], 'c': [1.25, 0.75]}) >>> df abc 0 1.5 0.25 1.25 1 2.5 2.75 0.75 

La media de cada fila es sencilla de calcular:

 >>> df.mean(axis=1) 0 1 1 2 dtype: float64 

Para eliminar las filas de DataFrame, solo reste los valores medios de las filas de df esta manera:

 >>> df.sub(df.mean(axis=1), axis=0) abc 0 0.5 -0.75 0.25 1 0.5 0.75 -1.25 

Además de la excelente respuesta de @ ajcr, es posible que desee considerar la reorganización de la forma en que almacena sus datos.

La forma en que lo está haciendo en este momento, con diferentes muestras en diferentes columnas, es la forma en que se representaría si estuviera utilizando una hoja de cálculo, pero esta podría no ser la forma más útil de representar sus datos.

Normalmente, cada columna representa una información única sobre una única entidad del mundo real . El ejemplo típico de este tipo de datos es una persona:

 id name hair_colour Age 1 Bob Brown 25 

Realmente, sus diferentes muestras son diferentes entidades del mundo real .

Por lo tanto, sugeriría tener un índice de dos niveles para describir cada pieza de información. Esto hace que la manipulación de sus datos de la forma que desee sea mucho más conveniente.

Así:

 >>> df = pd.DataFrame([['Sn',1,2,3],['Pb',2,4,6]], columns=['element', 'A', 'B', 'C']).set_index('element') >>> df.columns.name = 'sample' >>> df # This is how your DataFrame looks at the moment sample ABC element Sn 1 2 3 Pb 2 4 6 >>> # Now make those columns into a second level of index >>> df = df.stack() >>> df element sample Sn A 1 B 2 C 3 Pb A 2 B 4 C 6 

Ahora tenemos toda la funcionalidad deliciosa de groupby a nuestra disposición:

 >>> demean = lambda x: x - x.mean() >>> df.groupby(level='element').transform(demean) element sample Sn A -1 B 0 C 1 Pb A -2 B 0 C 2 

Cuando ve sus datos de esta manera, encontrará que muchos, muchos casos de uso que solían ser DataFrames varias columnas son en realidad Series MultiIndexed, y tiene mucho más poder sobre cómo se representan y transforman los datos.