Je veux filtrer toutes les colonnes avec des valeurs manquantes supérieures à 90 PCT dans Spark afin que je puisse les supprimer de l'analyse.
J'ai essayé le code suivant, mais cela prend une éternité:
from pyspark.sql.functions import isnull, when, count, col total_rows = df.count() features_missing_above_90 = [] for feature in df.columns: feature_nulls = df.filter(df[feature].isNull()).count() result = (feature_nulls/total_rows) if(result>0.9): features_missing_above_90.append(df[feature].str) print(features_missing_above_90)
Quelqu'un peut-il m'aider?
Merci!
3 Réponses :
Je pense que vous vouliez ajouter le nom de la colonne à la liste, pas la représentation sous forme de chaîne du dataframe.
total_rows = df.count() features_missing_above_90 = [] for feature in df.columns: feature_nulls = df.filter(df[feature].isNull()).count() result = (feature_nulls / total_rows) if (result > 0.9): features_missing_above_90.append(feature) df = df.select([col for col in df.columns if col not in features_missing_above_90])
Remplacez df.count()
par une valeur flottante, sans cela, votre condition if ne s'exécutera pas car un entier / entier ne vous donnera qu'un entier.
>>> df \ ... .select(F.array(*columns).alias("columns")) \ ... .select(F.explode(F.col("columns")).alias("columns")) \ ... .select(F.collect_set(F.col("columns")).alias("missing")) \ ... .collect()[0] Row(missing=[u'b', u'e'])
>>> columns = map(lambda c: F.when(((F.count(F.col("*")) - F.size(F.collect_set(F.col(c))))/F.count(F.col("*"))) > F.lit(threshold), F.lit(c)),df.columns)
>>> threshold = 0.7
>>> df.show() +----+----+----+----+----+----+ | a| b| c| d| e| f| +----+----+----+----+----+----+ | 1|null| 2| 3|null| 4| | 2|null|null| 5|null| 6| | 4| 2| 1| 4| 5| 6| | 5|null|null|null|null| 4| |null|null|null|null|null|null| +----+----+----+----+----+----+
Vous pouvez également essayer le code ci-dessous.
>>> print(features_missing_above_90) ['b', 'e']
>>> for feature in df.columns: ... feature_nulls = df.filter(F.col(feature).isNull()).count() ... result = feature_nulls/total_rows ... if(result>0.7): ... features_missing_above_90.append(feature) ...
Application de la logique
>>> features_missing_above_90 = []
>>> total_rows = float(df.count())
Salut, merci pour votre message. Il serait peut-être préférable d'utiliser collect_list au lieu de collect_set dans la fonction map pour traiter les champs catégoriels qui ont des valeurs répétées, étant donné que collect_set ignore les doublons.
Ok, il est difficile d'accéder aux colonnes en double .. si vous avez des colonnes en double dans la trame de données, dites les noms de colonnes a, a .. comment obtenir des valeurs seulement après une colonne ..?
Après avoir analysé le code par @Srinivas, j'ai fait quelques modifications mineures à des fins de performances:
threshold = 0.9 columns = map(lambda c: F.when( ((F.sum(F.col(c).isNull().cast("double"))) / (F.count("*"))) >= F.lit(threshold), F.lit(c)),df.columns) lst_columns_missing = df \ .select(F.array(*columns).alias("columns")) \ .select(F.explode(F.col("columns")).alias("columns")) \ .select(F.collect_set(F.col("columns")).alias("missing")) \ .collect()[0]