新しいsparkデータフレームAPIを見ると、データフレーム列を変更できるかどうかは不明です。
データフレームの行x
列y
の値を変更するにはどうすればよいですか?
pandas
では、これはdf.ix[x,y] = new_value
になります
編集:以下の説明を統合すると、既存のデータフレームは不変であるため変更できませんが、必要な変更を加えた新しいデータフレームを返すことができます。
np.where
のように、条件に基づいて列の値を単に置き換えたい場合:
from pyspark.sql import functions as F
update_func = (F.when(F.col('update_col') == replace_val, new_value)
.otherwise(F.col('update_col')))
df = df.withColumn('new_column_name', update_func)
列で何らかの操作を実行し、データフレームに追加される新しい列を作成する場合:
import pyspark.sql.functions as F
import pyspark.sql.types as T
def my_func(col):
do stuff to column here
return transformed_value
# if we assume that my_func returns a string
my_udf = F.UserDefinedFunction(my_func, T.StringType())
df = df.withColumn('new_column_name', my_udf('update_col'))
新しい列に古い列と同じ名前を付けたい場合、追加のステップを追加できます。
df = df.drop('update_col').withColumnRenamed('new_column_name', 'update_col')
列をそのように変更することはできませんが、列を操作して、その変更を反映する新しいDataFrameを返すことができます。そのためには、最初に適用する操作を実装するUserDefinedFunction
を作成し、次にその関数をターゲット列のみに選択的に適用します。 Pythonの場合:
from pyspark.sql.functions import UserDefinedFunction
from pyspark.sql.types import StringType
name = 'target_column'
udf = UserDefinedFunction(lambda x: 'new_value', StringType())
new_df = old_df.select(*[udf(column).alias(name) if column == name else column for column in old_df.columns])
new_df
のスキーマはold_df
と同じになりました(old_df.target_column
もStringType
型であると仮定します)が、列target_column
のすべての値はnew_value
になります。
一般に、列を更新するとき、古い値を新しい値にマップします。 UDFを使用せずにpysparkでこれを行う方法は次のとおりです。
# update df[update_col], mapping old_value --> new_value
from pyspark.sql import functions as F
df = df.withColumn(update_col,
F.when(df[update_col]==old_value,new_value).
otherwise(df[update_col])).
DataFrames
はRDDに基づいています。 RDDは不変の構造であり、オンサイトで要素を更新することはできません。値を変更するには、SQLに似たDSLまたはmap
のようなRDD操作を使用して、元のデータフレームを変換して新しいDataFrameを作成する必要があります。
強く推奨されるスライドデッキ: 大規模データサイエンス向けのSparkでのDataFrameの紹介 。
maasg が示すように、古いDataFrameに適用されたマップの結果から新しいDataFrameを作成できます。 2つの行がある特定のDataFrame df
の例:
val newDf = sqlContext.createDataFrame(df.map(row =>
Row(row.getInt(0) + SOMETHING, applySomeDef(row.getAs[Double]("y")), df.schema)
列のタイプが変更された場合、df.schema
の代わりに正しいスキーマを与える必要があることに注意してください。利用可能なメソッドについては、org.Apache.spark.sql.Row
のAPIを確認してください: https://spark.Apache.org/docs/latest/api/Java/org/Apache/spark/sql/Row.html
[更新]またはScalaでUDFを使用:
import org.Apache.spark.sql.functions._
val toLong = udf[Long, String] (_.toLong)
val modifiedDf = df.withColumn("modifiedColumnName", toLong(df("columnName"))).drop("columnName")
列名を同じままにする必要がある場合は、名前を元に戻すことができます。
modifiedDf.withColumnRenamed("modifiedColumnName", "columnName")