Probablemente un duplicado, pero he pasado demasiado tiempo buscando en Google sin suerte. Supongamos que tengo un marco de datos:
import pandas as pd data = {"letters": ["a", "a", "a", "b", "b", "b"], "boolean": [True, True, True, True, True, False], "numbers": [1, 2, 3, 1, 2, 3]} df = pd.DataFrame(data) dfQuiero 1) agrupar por letras, 2) tomar la media de los números si todos los valores booleanos tienen el mismo valor. En RI escribiría:
library(dplyr) df %>% group_by(letters) %>% mutate( condition = n_distinct(boolean) == 1, numbers = ifelse(condition, mean(numbers), numbers) ) %>% select(-condition)Esto daría como resultado la siguiente salida:
# A tibble: 6 x 3 # Groups: letters [2] letters boolean numbers <chr> <lgl> <dbl> 1 a TRUE 2 2 a TRUE 2 3 a TRUE 2 4 b TRUE 1 5 b TRUE 2 6 b FALSE 3¿Cómo lo harías usando Python pandas?
Podemos usar lazy groupby y transform :
g = df.groupby('letters') df.loc[g['boolean'].transform('all'), 'numbers'] = g['numbers'].transform('mean')Producción:
letters boolean numbers 0 a True 2 1 a True 2 2 a True 2 3 b True 1 4 b True 2 5 b False 3Otra forma sería usar np.where. donde un grupo tiene un valor único, encuentre la media. Donde no guarda los números. Código a continuación
df['numbers'] =np.where(df.groupby('letters')['boolean'].transform('nunique')==1,df.groupby('letters')['numbers'].transform('mean'), df['numbers']) letters boolean numbers 0 a True 2.0 1 a True 2.0 2 a True 2.0 3 b True 1.0 4 b True 2.0 5 b False 3.0Alternativamente, enmascare donde la condición no se aplica mientras calcula la media.
m=df.groupby('letters')['boolean'].transform('nunique')==1 df.loc[m, 'numbers']=df[m].groupby('letters')['numbers'].transform('mean')datar es otra solución para usted:
>>> import pandas as pd >>> data = {"letters": ["a", "a", "a", "b", "b", "b"], ... "boolean": [True, True, True, True, True, False], ... "numbers": [1, 2, 3, 1, 2, 3]} >>> df = pd.DataFrame(data) >>> >>> from datar.all import f, group_by, mutation, n_distinct, if_else, mean, select >>> df >> group_by(f.letters) \ ... >> mutate( ... condition=n_distinct(f.boolean) == 1, ... numbers = if_else(f.condition, mean(f.numbers), f.numbers) ... ) \ ... >> select(~f.condition) letters boolean numbers <object> <bool> <float64> 0 a True 2.0 1 a True 2.0 2 a True 2.0 3 b True 1.0 4 b True 2.0 5 b False 3.0 [Groups: letters (n=2)]Como está comparando directamente con R, preferiría usar siuba en lugar de pandas :
from siuba import mutate, if_else, _, select, group_by, ungroup df1 = df >>\ group_by(_.letters) >> \ mutate( condition = _.boolean.unique().size == 1, numbers = if_else(_.condition, _.numbers.mean(), _.numbers) ) >>\ ungroup() >> select(-_.condition) print(df1) letters boolean numbers 0 a True 2.0 1 a True 2.0 2 a True 2.0 3 b True 1.0 4 b True 2.0 5 b False 3.0 Tenga en cuenta que >> es la tubería. Agregué \ para pasar a la siguiente línea. También ten en cuenta que para referirte a las variables usas _.variable
Parece que su código R tiene un problema. En R, debería usar condition = all(boolean) en lugar del código que tiene. Eso se traducirá a condition = boolean.all() en Python