web-dev-qa-db-ja.com

null要素を使用してpysparkデータフレームread.csvにスキーマを設定します

でインポートしたときにデータセット(例)があります

df = spark.read.csv(filename, header=True, inferSchema=True)
df.show()

'NA'の列をstringType()として割り当てます。ここで、IntegerType()(またはByteType())にします。

inferSchema

それから私は設定しようとしました

schema = StructType([
    StructField("col_01", IntegerType()),
    StructField("col_02", DateType()),
    StructField("col_03", IntegerType())
])
df = spark.read.csv(filename, header=True, schema=schema)
df.show()

出力には、 'col_03' = nullの行全体がnullであることが示されます。

entire_row_null

ただし、col_01およびcol_02は、で呼び出された場合に適切なデータを返します。

df.select(['col_01','col_02']).show()

row_actually_not_null

col_3のデータ型をポストキャストすることでこれを回避する方法を見つけることができます

df = spark.read.csv(filename, header=True, inferSchema=True)
df = df.withColumn('col_3',df['col_3'].cast(IntegerType()))
df.show()

import_then_cast

、しかし、それは理想的ではないと思います。スキーマを設定して各列のデータ型を直接割り当てることができれば、はるかに良いでしょう。

誰かが私が間違っていることを私に導くことができますか?または、インポート後にデータ型をキャストすることが唯一の解決策ですか? 2つのアプローチのパフォーマンスに関するコメント(スキーマの割り当てを機能させることができる場合)も歓迎します。

ありがとうございました、

4
ctl

nullValueを使用して、sparkのcsvローダーに新しいnull値を設定できます。次のようなcsvファイルの場合:

col_01,col_02,col_03
111,2007-11-18,3
112,2002-12-03,4
113,2007-02-14,5
114,2003-04-16,NA
115,2011-08-24,2
116,2003-05-03,3
117,2001-06-11,4
118,2004-05-06,NA
119,2012-03-25,5
120,2006-10-13,4

スキーマの強制:

schema = StructType([
    StructField("col_01", IntegerType()),
    StructField("col_02", DateType()),
    StructField("col_03", IntegerType())
])

あなたが得るでしょう:

df = spark.read.csv(filename, header=True, nullValue='NA', schema=schema)
df.show()
df.printSchema()

    +------+----------+------+
    |col_01|    col_02|col_03|
    +------+----------+------+
    |   111|2007-11-18|     3|
    |   112|2002-12-03|     4|
    |   113|2007-02-14|     5|
    |   114|2003-04-16|  null|
    |   115|2011-08-24|     2|
    |   116|2003-05-03|     3|
    |   117|2001-06-11|     4|
    |   118|2004-05-06|  null|
    |   119|2012-03-25|     5|
    |   120|2006-10-13|     4|
    +------+----------+------+

    root
     |-- col_01: integer (nullable = true)
     |-- col_02: date (nullable = true)
     |-- col_03: integer (nullable = true)
2
MaFF

これを一度試してください-(ただし、これはすべての列を文字列型として読み取ります。要件に応じてカーストを入力できます)

import csv
from pyspark.sql.types import IntegerType

data = []
with open('filename', 'r' ) as doc:
    reader = csv.DictReader(doc)
    for line in reader:
        data.append(line)

df = sc.parallelize(data).toDF()
df = df.withColumn("col_03", df["col_03"].cast(IntegerType()))
0
user7348570