Spark欠損値のあるデータフレームがあります。欠損値をその列の平均値に置き換えることで簡単な代入を実行したいと思います。私はSparkに非常に慣れていないので、このロジックを実装するのに苦労しています。
a)これを単一の列(列Aとしましょう)で実行するには、次のコード行が機能するようです。
df.withColumn("new_Col", when($"ColA".isNull, df.select(mean("ColA"))
.first()(0).asInstanceOf[Double])
.otherwise($"ColA"))
b)しかし、データフレームのすべての列に対してこれを行う方法を理解することができませんでした。 Map関数を試してみましたが、データフレームの各行をループしていると思います
c)SO- here 。)にも同様の質問があります。また、(集計テーブルと合体を使用した)ソリューションは気に入っていましたが、これは、各列をループすることによってこれを行う方法です(私はRから来ているので、lapplyのような高次関数を使用して各列をループするのが私には自然に思えます)。
ありがとう!
スパーク> = 2.2
org.Apache.spark.ml.feature.Imputer
を使用できます(平均と中央値の両方の戦略をサポートしています)。
スカラ:
import org.Apache.spark.ml.feature.Imputer
val imputer = new Imputer()
.setInputCols(df.columns)
.setOutputCols(df.columns.map(c => s"${c}_imputed"))
.setStrategy("mean")
imputer.fit(df).transform(df)
Python:
from pyspark.ml.feature import Imputer
imputer = Imputer(
inputCols=df.columns,
outputCols=["{}_imputed".format(c) for c in df.columns]
)
imputer.fit(df).transform(df)
スパーク<2.2
はい、どうぞ:
import org.Apache.spark.sql.functions.mean
df.na.fill(df.columns.Zip(
df.select(df.columns.map(mean(_)): _*).first.toSeq
).toMap)
どこ
df.columns.map(mean(_)): Array[Column]
各列の平均を計算し、
df.select(_: *).first.toSeq: Seq[Any]
集計された値を収集し、行をSeq[Any]
に変換します(これは最適ではないことはわかっていますが、これは私たちが操作する必要があるAPIです)。
df.columns.Zip(_).toMap: Map[String,Any]
列名からその平均にマップするaMap: Map[String, Any]
を作成し、最後に:
df.na.fill(_): DataFrame
次を使用して欠損値を埋めます:
fill: Map[String, Any] => DataFrame
DataFrameNaFunctions
から。
NaN
エントリを単一化するには、次のように置き換えます。
df.select(df.columns.map(mean(_)): _*).first.toSeq
と:
import org.Apache.spark.sql.functions.{col, isnan, when}
df.select(df.columns.map(
c => mean(when(!isnan(col(c)), col(c)))
): _*).first.toSeq
PySpark <2.2の(平均ではなく)中央値を代入するため
## filter numeric cols
num_cols = [col_type[0] for col_type in filter(lambda dtype: dtype[1] in {"bigint", "double", "int"}, df.dtypes)]
### Compute a dict with <col_name, median_value>
median_dict = dict()
for c in num_cols:
median_dict[c] = df.stat.approxQuantile(c, [0.5], 0.001)[0]
次に、na.fill
df_imputed = df.na.fill(median_dict)
PySparkの場合、これは私が使用したコードです。
_mean_dict = { col: 'mean' for col in df.columns }
col_avgs = df.agg( mean_dict ).collect()[0].asDict()
col_avgs = { k[4:-1]: v for k,v in col_avgs.iteritems() }
df.fillna( col_avgs ).show()
_
4つのステップは次のとおりです。
mean_dict
_を作成し、列名を集計演算にマッピングします(平均)col_avgs
_col_avgs
_の列名は_avg(
_で始まり、_)
_で終わります。 avg(col1)
。括弧を取り除きます。col_avgs
_を使用して、データフレームの列に平均を入力します