データフレームに列を追加することは可能ですか?最も効率的な方法は何ですか?
より具体的には、列は既存のデータフレームの行IDとして機能します。
ファイルを読み取ってトークン化しない単純なケースでは、次のように考えることができます(Scalaで)が、エラー(3行目)で完了し、とにかく可能な最良のルートのようには見えません:
var dataDF = sc.textFile("path/file").toDF()
val rowDF = sc.parallelize(1 to DataDF.count().toInt).toDF("ID")
dataDF = dataDF.withColumn("ID", rowDF("ID"))
私が質問を投稿してからしばらく経ちましたが、他の人も答えを求めているようです。以下は私が見つけたものです。
したがって、元のタスクは、行識別子を持つ列(基本的に、シーケンス1 to numRows
)を特定のデータフレームに追加することでした。そのため、行の順序/存在を追跡できます(サンプリング時など)。これはこれらの線に沿って何かによって達成できます:
sqlContext.textFile(file).
zipWithIndex().
map(case(d, i)=>i.toString + delimiter + d).
map(_.split(delimiter)).
map(s=>Row.fromSeq(s.toSeq))
データフレームに列を追加する一般的なケースについて:
Spark APIのこの機能に「最も近い」ものは、withColumn
およびwithColumnRenamed
です。 Scala docs によると、前者は、列を追加して新しいDataFrameを返します。私の意見では、これは少し混乱して不完全な定義です。これらの関数は両方ともthis
データフレームのみで操作できます。つまり、2つのデータフレームdf1
およびdf2
が列col
である場合:
val df = df1.withColumn("newCol", df1("col") + 1) // -- OK
val df = df1.withColumn("newCol", df2("col") + 1) // -- FAIL
したがって、既存のデータフレームの列を必要な形状に変換できない場合、withColumn
またはwithColumnRenamed
を使用して任意の列(スタンドアロンまたは他のデータフレーム)を追加することはできません。
上記でコメントしたように、回避策はjoin
を使用することです-これはかなり面倒ですが、可能ですが、上記のような一意のキーをzipWithIndex
で両方のデータフレームまたは列に接続すると動作します。効率は...
データフレームに列を追加することは、分散環境にとって簡単な機能ではなく、そのための効率的で適切な方法がまったくない可能性があることは明らかです。しかし、パフォーマンスの警告があっても、このコア機能を利用できるようにすることは依然として非常に重要だと思います。
spark 1.3で動作するかどうかはわかりませんが、spark 1.5ではwithColumnを使用します。
import sqlContext.implicits._
import org.Apache.spark.sql.functions._
df.withColumn("newName",lit("newValue"))
データフレームの既存の列に関連しない値を使用する必要がある場合に使用します
これは@NehaMの答えに似ていますが、より簡単です
上記の答えから助けを借りました。ただし、DataFrame
を変更したい場合は不完全であり、現在のAPIはSpark 1.6
で少し異なります。 zipWithIndex()
は、各行と対応するインデックスを含む(Row, Long)
のTuple
を返します。これを使用して、必要に応じて新しいRow
を作成できます。
val rdd = df.rdd.zipWithIndex()
.map(indexedRow => Row.fromSeq(indexedRow._2.toString +: indexedRow._1.toSeq))
val newstructure = StructType(Seq(StructField("Row number", StringType, true)).++(df.schema.fields))
sqlContext.createDataFrame(rdd, newstructure ).show
これが役立つことを願っています。
以下のように row_number と Window function を使用して、データフレーム内の各行の個別のIDを取得できます。
df.withColumn("ID", row_number() over Window.orderBy("any column name in the dataframe"))
monotonically_increasing_id
も使用できます。
df.withColumn("ID", monotonically_increasing_id())
そして、いくつかの 他の方法 もあります。