Me gustaría promediar ciertos valores de columna dependiendo de si se cumple una condición en otra columna. Específicamente, si la columna 1 en el marco de datos a continuación es <1700, quiero incluir el valor correspondiente en esa fila de la columna 51 en mi cálculo promedio. Y si la columna 2 <1700, también quiero incluir el valor en esa fila de la columna 52 en mi cálculo promedio.
Entonces, para la fila 0, la nueva columna calculada para esa fila sería 64 (promedio de 65 y 63). Para la fila 1, el promedio sería solo 80 (valor de la columna 51) ya que ni las columnas 2 ni 3 eran menores de 1700 y, por lo tanto, no se incluyeron en el cálculo promedio.
Este es un ejemplo simplificado ya que mi marco de datos real tiene aproximadamente 10 columnas para condiciones con 10 columnas de valores correspondientes para promediar.
Como posible complejidad, los encabezados de las columnas son números en lugar de etiquetas de texto tradicionales y no se refieren al orden de esa columna en el marco de datos, ya que he excluido ciertas columnas cuando importé el archivo csv. En otras palabras, la columna 51 no es la columna 51 en el marco de datos.
Cuando ejecuto el siguiente código, aparece el siguiente error:
ValueError: ("Ningún eje llamado 1 para el tipo de objeto", 'ocurrió en el índice 0')
¿Hay una manera más eficiente de codificar esto y evitar este error? ¡Gracias por tu ayuda!
import pandas as pd
import numpy as np
test_df = pd.DataFrame({1:[1600,1600,1600,1700,1800],2:[1500,2000,1400,1500,2000],
3:[2000,2000,2000,2000,2000],51:[65,80,75,80,75],52:[63,82,85,85,75],53:[83,80,75,76,78]})
test_df
1 2 3 51 52 53
0 1600 1500 2000 65 63 83
1 1600 2000 2000 80 82 80
2 1600 1400 2000 75 85 75
3 1700 1500 2000 80 85 76
4 1800 2000 2000 75 75 78
def calc_mean_based_on_conditions(row):
list_of_columns_to_average = []
for i in range(1,4):
if row[i] < 1700:
list_of_columns_to_average.append(i+50)
if not list_of_columns_to_average:
return np.nan
else:
return row[(list_of_columns_to_average)].mean(axis=1)
test_df['MeanValue'] = test_df.apply(calc_mean_based_on_conditions, axis=1)
3 respuestas
Algo muy relevante (que admite int como nombres de columna) - https://github.com/theislab/anndata / temas / 31
Debido a este error / problema, convertí los nombres de columna para escribir string:
test_df = pd.DataFrame({'1':[1600,1600,1600,1700,1800],'2':[1500,2000,1400,1500,2000],
'3':[2000,2000,2000,2000,2000],'51':[65,80,75,80,75],'52':[63,82,85,85,75],'53':
[83,80,75,76,78]})
Creó un nuevo marco de datos - new_df para cumplir con los requisitos
new_df = test_df[['1', '2', '3']].where(test_df[['1','2','3']]<1700).notnull()
New_df ahora se ve así
1 2 3
0 True True False
1 True False False
2 True True False
3 False True False
4 False False False
Luego simplemente cambie el nombre de la columna y verifique usando 'where'
new_df = new_df.rename(columns={"1": "51", "2":"52", "3":"53"})
test_df['mean_value'] = test_df[['51', '52', '53']].where(new_df).mean(axis=1)
Esto debería darle el resultado deseado:
1 2 3 51 52 53 mean_value
0 1600 1500 2000 65 63 83 64.0
1 1600 2000 2000 80 82 80 80.0
2 1600 1400 2000 75 85 75 80.0
3 1700 1500 2000 80 85 76 85.0
4 1800 2000 2000 75 75 78 NaN
Eliminé mi otra respuesta porque estaba yendo por el camino equivocado. Lo que desea hacer es generar una máscara de sus columnas condicionales, luego usar esa máscara para aplicar una función a otras columnas. En este caso, 1 corresponde a 51, 2 a 52, etc.
import pandas as pd
import numpy as np
test_df = pd.DataFrame({1:[1600,1600,1600,1700,1800],2:[1500,2000,1400,1500,2000],
3:[2000,2000,2000,2000,2000],51:[65,80,75,80,75],52:[63,82,85,85,75],53:[83,80,75,76,78]})
test_df
1 2 3 51 52 53
0 1600 1500 2000 65 63 83
1 1600 2000 2000 80 82 80
2 1600 1400 2000 75 85 75
3 1700 1500 2000 80 85 76
4 1800 2000 2000 75 75 78
# create dictionary to map columns to one another
l1=list(range(1,4))
l2=list(range(50,54))
d = {k:v for k,v in zip(l1,l2)}
d
{1: 51, 2: 52, 3: 53}
temp=test_df[l1] > 1700 # Subset initial dataframe, generate mask
for _, row in temp.iterrows(): #iterate through subsetted data
list_of_columns_for_mean=list() # list of columns for later computation
for k, v in d.items(): #iterate through each k:v and evaluate conditional for each row
if row[k]:
list_of_columns_for_mean.append(v)
# the rest should be pretty easy to figure out
Esta no es una solución elegante, pero es una solución. Desafortunadamente, se me acabó el tiempo para dedicarlo, pero espero que esto te lleve a una mejor dirección.
Probablemente haya una forma mejor y vectorizada de hacerlo, pero podría hacerlo sin la función
import numpy as np
import pandas as pd
from collections import defaultdict
test_df = pd.DataFrame({1:[1600,1600,1600,1700,1800],2:[1500,2000,1400,1500,2000],
3:[2000,2000,2000,2000,2000],51:[65,80,75,80,75],52:[63,82,85,85,75],53:[83,80,75,76,78]})
# List of columns that you're applying the condition to
condition_cols = list(range(1,4))
# Get row and column indices where this condition is true
condition = np.where(test_df[condition_cols].lt(1700))
# make a dictionary mapping row to true columns
cond_map = defaultdict(list)
for r,c in zip(*condition):
cond_map[r].append(c)
# Get the means of true columns
means = []
for row in range(len(test_df)):
if row in cond_map:
temp = []
for col in cond_map[row]:
# Needs 51 because of Python indexing starting at zero + 50
temp.append(test_df.loc[row, col+51])
means.append(temp)
else:
# If the row has no true columns (i.e row 4)
means.append(np.nan)
test_df['Means'] = [np.mean(l) for l in means]
El problema es indexar columnas de filas verdaderas y de forma vectorizada.
Preguntas relacionadas
Nuevas preguntas
python
Python es un lenguaje de programación multipropósito, de tipificación dinámica y de múltiples paradigmas. Está diseñado para ser rápido de aprender, comprender y usar, y hacer cumplir una sintaxis limpia y uniforme. Tenga en cuenta que Python 2 está oficialmente fuera de soporte a partir del 01-01-2020. Aún así, para preguntas de Python específicas de la versión, agregue la etiqueta [python-2.7] o [python-3.x]. Cuando utilice una variante de Python (por ejemplo, Jython, PyPy) o una biblioteca (por ejemplo, Pandas y NumPy), inclúyala en las etiquetas.