web-dev-qa-db-ja.com

pysparkデータフレームを2つの行ごとにスライスする方法

私はDatabricksで働いています。

500行を含むデータフレームがあります。100行を含む2つのデータフレームと、残りの400行を含むもう1つのデータフレームを作成したいと思います。

+--------------------+----------+
|              userid| eventdate|
+--------------------+----------+
|00518b128fc9459d9...|2017-10-09|
|00976c0b7f2c4c2ca...|2017-12-16|
|00a60fb81aa74f35a...|2017-12-04|
|00f9f7234e2c4bf78...|2017-05-09|
|0146fe6ad7a243c3b...|2017-11-21|
|016567f169c145ddb...|2017-10-16|
|01ccd278777946cb8...|2017-07-05|

以下を試しましたが、エラーが表示されます

df1 = df[:99]
df2 = df[100:499]


TypeError: unexpected item type: <type 'slice'>
8
Data_101

当初、私はあなたがコラムをスライスしたいと思っていたと誤解していました。行のサブセットを選択する場合、1つの方法は monotonically_increasing_id() を使用してインデックス列を作成することです。ドキュメントから:

生成されるIDは、単調に増加し、一意であることが保証されていますが、連続的ではありません。

このIDを使用してデータフレームを並べ替え、limit()を使用してサブセット化することで、必要な行を正確に取得できます。

例えば:

import pyspark.sql.functions as f
import string

# create a dummy df with 500 rows and 2 columns
N = 500
numbers = [i%26 for i in range(N)]
letters = [string.ascii_uppercase[n] for n in numbers]

df = sqlCtx.createDataFrame(
    Zip(numbers, letters),
    ('numbers', 'letters')
)

# add an index column
df = df.withColumn('index', f.monotonically_increasing_id())

# sort ascending and take first 100 rows for df1
df1 = df.sort('index').limit(100)

# sort descending and take 400 rows for df2
df2 = df.sort('index', ascending=False).limit(400)

これがあなたが望むことをしたことを確認するだけです:

df1.count()
#100
df2.count()
#400

また、インデックス列が重複していないことを確認できます。

df1.select(f.min('index').alias('min'), f.max('index').alias('max')).show()
#+---+---+
#|min|max|
#+---+---+
#|  0| 99|
#+---+---+

df2.select(f.min('index').alias('min'), f.max('index').alias('max')).show()
#+---+----------+
#|min|       max|
#+---+----------+
#|100|8589934841|
#+---+----------+
8
pault

Sparkデータフレームは、あなたが書いているようにインデックスを作成することはできません。作成にheadメソッドを使用して、上位n行を取得できます。これにより、データフレームではなくRow()オブジェクトのリストが返されます。したがって、それらをデータフレームに変換し、元のデータフレームから減算を使用して残りの行を取得できます。

#Take the 100 top rows convert them to dataframe 
#Also you need to provide the schema also to avoid errors
df1 = sqlContext.createDataFrame(df.head(100), df.schema)

#Take the rest of the rows
df2 = df.subtract(df1)

spark 2.0以降で作業している場合は、spark sqlContextの代わりにSparkSessionも使用できます。また、最初の100行を取得することに興味がなく、ランダムに分割したい場合は、次のように randomSplit を使用できます。

df1,df2 = df.randomSplit([0.20, 0.80],seed=1234)
7
Michail N

両方のデータフレームに同じ行があることを気にしない場合は、sampleを使用できます。たとえば354行のデータフレームがあります。

>>> df.count()
354

>>> df.sample(False,0.5,0).count() //approx. 50%
179

>>> df.sample(False,0.1,0).count() //approx. 10%
34

あるいは、重複が存在せずに厳密に分割したい場合は、

df1 = df.limit(100)     //100 rows
df2 = df.subtract(df1)  //Remaining rows
2
Bala