ti-enxame.com

Pandas - Groupby com fórmula condicional

   Survived  SibSp  Parch
0         0      1      0
1         1      1      0
2         1      0      0
3         1      1      0
4         0      0      1

Dado o quadro de dados acima, existe uma maneira elegante de groupby com uma condição? Quero dividir os dados em dois grupos com base nas seguintes condições:

(df['SibSp'] > 0) | (df['Parch'] > 0) =   New Group -"Has Family"
 (df['SibSp'] == 0) & (df['Parch'] == 0) = New Group - "No Family"

então pegue os meios de ambos os grupos e termine com uma saída como esta:

               SurvivedMean
 Has Family    Mean
 No Family     Mean

Isso pode ser feito usando groupby ou eu teria que acrescentar uma nova coluna usando a instrução condicional acima?

5
George Vince

Uma maneira fácil de agrupar é usar a soma dessas duas colunas. Se um deles for positivo, o resultado será maior que 1. E groupby aceita uma matriz arbitrária desde que o comprimento seja igual ao comprimento do DataFrame, para que você não precise adicionar uma nova coluna.

family = np.where((df['SibSp'] + df['Parch']) >= 1 , 'Has Family', 'No Family')
df.groupby(family)['Survived'].mean()
Out: 
Has Family    0.5
No Family     1.0
Name: Survived, dtype: float64
9
ayhan

Use apenas uma condição se nunca os valores nas colunas SibSp e Parch forem menores que 0:

m1 = (df['SibSp'] > 0) | (df['Parch'] > 0)

df = df.groupby(np.where(m1, 'Has Family', 'No Family'))['Survived'].mean()
print (df)
Has Family    0.5
No Family     1.0
Name: Survived, dtype: float64

Se for impossível, use primeiro as duas condições:

m1 = (df['SibSp'] > 0) | (df['Parch'] > 0)
m2 = (df['SibSp'] == 0) & (df['Parch'] == 0)
a = np.where(m1, 'Has Family', 
    np.where(m2, 'No Family', 'Not'))

df = df.groupby(a)['Survived'].mean()
print (df)
Has Family    0.5
No Family     1.0
Name: Survived, dtype: float64
1
jezrael

Você pode definir suas condições em uma lista e usar a função group_by_condition abaixo para criar uma lista filtrada para cada condição. Depois, você pode selecionar os itens resultantes usando a correspondência de padrões:

df = [
  {"Survived": 0, "SibSp": 1, "Parch": 0},
  {"Survived": 1, "SibSp": 1, "Parch": 0},
  {"Survived": 1, "SibSp": 0, "Parch": 0}]

conditions = [
  lambda x: (x['SibSp'] > 0) or (x['Parch'] > 0),  # has family
  lambda x: (x['SibSp'] == 0) and (x['Parch'] == 0)  # no family
]

def group_by_condition(l, conditions):
    return [[item for item in l if condition(item)] for condition in conditions]

[has_family, no_family] = group_by_condition(df, conditions)
1
Zwackelmann