web-dev-qa-db-fra.com

Comment supprimer des colonnes qui ont les mêmes valeurs dans toutes les lignes via pandas ou spark dataframe?

Supposons que j'ai des données similaires à la suivante:

  index id   name  value  value2  value3  data1  val5
    0  345  name1    1      99      23     3      66
    1   12  name2    1      99      23     2      66
    5    2  name6    1      99      23     7      66

Comment pouvons-nous supprimer toutes ces colonnes comme (value, value2, value3) où toutes les lignes ont les mêmes valeurs, dans une ou plusieurs commandes utilisant python?

Considérez que nous avons de nombreuses colonnes similaires à value, value2, value3...value200.

Production:

   index id      name   data1
        0  345  name1    3
        1   12  name2    2
        5    2  name6    7
22
CYAN CEVI

Ce que nous pouvons faire, c'est applynunique pour calculer le nombre de valeurs uniques dans le df et supprimer les colonnes qui n'ont qu'une seule valeur unique:

In [285]:
nunique = df.apply(pd.Series.nunique)
cols_to_drop = nunique[nunique == 1].index
df.drop(cols_to_drop, axis=1)

Out[285]:
   index   id   name  data1
0      0  345  name1      3
1      1   12  name2      2
2      5    2  name6      7

Une autre façon est de simplement diff les colonnes numériques et sums les:

In [298]:
cols = df.select_dtypes([np.number]).columns
diff = df[cols].diff().sum()
df.drop(diff[diff== 0].index, axis=1)
​
Out[298]:
   index   id   name  data1
0      0  345  name1      3
1      1   12  name2      2
2      5    2  name6      7

Une autre approche consiste à utiliser la propriété selon laquelle l'écart-type sera nul pour une colonne de même valeur:

In [300]:
cols = df.select_dtypes([np.number]).columns
std = df[cols].std()
cols_to_drop = std[std==0].index
df.drop(cols_to_drop, axis=1)

Out[300]:
   index   id   name  data1
0      0  345  name1      3
1      1   12  name2      2
2      5    2  name6      7

En fait, ce qui précède peut être fait dans une seule ligne:

In [306]:
df.drop(df.std()[(df.std() == 0)].index, axis=1)

Out[306]:
   index   id   name  data1
0      0  345  name1      3
1      1   12  name2      2
2      5    2  name6      7
30
EdChum

Une autre solution est set_index de la colonne qui n'est pas comparée, puis comparer la première ligne sélectionnée par iloc par eq avec tous les DataFrame et dernière utilisation boolean indexing :

df1 = df.set_index(['index','id','name',])
print (~df1.eq(df1.iloc[0]).all())
value     False
value2    False
value3    False
data1      True
val5      False
dtype: bool

print (df1.ix[:, (~df1.eq(df1.iloc[0]).all())].reset_index())
   index   id   name  data1
0      0  345  name1      3
1      1   12  name2      2
2      5    2  name6      7
3
jezrael