2017-08-22 8 views
0

Pysparkのネストした列のデータ型を変更するにはどうすればよいですか? rxampleでは、値のデータ型をstringからintに変更するにはどうすればよいですか?Pyspark:ネストした列のデータ型を変更する

参考:how to change a Dataframe column from String type to Double type in pyspark

{ 
    "x": "12", 
    "y": { 
     "p": { 
      "name": "abc", 
      "value": "10" 
     }, 
     "q": { 
      "name": "pqr", 
      "value": "20" 
     } 
    } 
} 
+0

1.この変更は、JSONファイルに保存された変更を、永続的である必要がありますか。または操作を実行している間に精度が必要ですか? – diek

+0

@diek jsonファイルに白い書込みが必要 –

答えて

2

あなたは今、あなたは

とyの列からのデータにアクセスすることができます

from pyspark import SQLContext 

sqlContext = SQLContext(sc) 
data_df = sqlContext.read.json("data.json", multiLine = True) 

data_df.printSchema() 

出力

root 
|-- x: long (nullable = true) 
|-- y: struct (nullable = true) 
| |-- p: struct (nullable = true) 
| | |-- name: string (nullable = true) 
| | |-- value: long (nullable = true) 
| |-- q: struct (nullable = true) 
| | |-- name: string (nullable = true) 
| | |-- value: long (nullable = true) 

を使用してJSONデータを読み取ることができます

出力

abc, 10 

[OK]を、解決策は正しいスキーマを持つ新しいネストされた列を追加し、間違ったスキーマ

from pyspark.sql.functions import * 
from pyspark.sql import Row 

df3 = spark.read.json("data.json", multiLine = True) 

# create correct schema from old 
c = df3.schema['y'].jsonValue() 
c['name'] = 'z' 
c['type']['fields'][0]['type']['fields'][1]['type'] = 'long' 
c['type']['fields'][1]['type']['fields'][1]['type'] = 'long' 

y_schema = StructType.fromJson(c['type']) 

# define a udf to populate the new column. Row are immuatable so you 
# have to build it from start. 

def foo(row): 
    d = Row.asDict(row) 
    y = {} 
    y["p"] = {} 
    y["p"]["name"] = d["p"]["name"] 
    y["p"]["value"] = int(d["p"]["value"]) 
    y["q"] = {} 
    y["q"]["name"] = d["q"]["name"] 
    y["q"]["value"] = int(d["p"]["value"]) 

    return(y) 
map_foo = udf(foo, y_schema) 

# add the column 
df3_new = df3.withColumn("z", map_foo("y")) 

# delete the column 
df4 = df3_new.drop("y") 


df4.printSchema() 

出力

root 
|-- x: long (nullable = true) 
|-- z: struct (nullable = true) 
| |-- p: struct (nullable = true) 
| | |-- name: string (nullable = true) 
| | |-- value: long (nullable = true) 
| |-- q: struct (nullable = true) 
| | |-- name: string (nullable = true) 
| | |-- value: long (nullable = true) 


df4.show() 

出力でカラムをドロップすることです

+---+-------------------+ 
| x|     z| 
+---+-------------------+ 
| 12|[[abc,10],[pqr,10]]| 
+---+-------------------+ 
+0

@aswinids質問を編集しました。これについて何か考えていますか? –

+0

@aswinids:助けてくれてありがとう。 jsonスキーマにdecima/timestampデータ型がありますか? –

+0

@aswinids:10の値を「10」に変更して「long」と入力すると、NULLが返されます。 –

0

任意の変数名を使用するのは簡単かもしれませんが、これは問題があり、PEP8に反します。そして、数値を扱う際には、そのような構造を反復する際に使用される一般的な名前、つまり値を避けることをお勧めします。

import json 

with open('random.json') as json_file: 
    data = json.load(json_file) 

for k, v in data.items(): 
    if k == 'y': 
     for key, item in v.items(): 
      item['value'] = float(item['value']) 


print(type(data['y']['p']['value'])) 
print(type(data['y']['q']['value'])) 
# mac → python3 make_float.py 
# <class 'float'> 
# <class 'float'> 
json_data = json.dumps(data, indent=4, sort_keys=True) 
with open('random.json', 'w') as json_file: 
    json_file.write(json_data) 

out json file

+0

この問題の重要な部分は、毎日約60GBのデータが作成されており、スケーラビリティを確保する必要があることと、なぜSparkが脱出したのかです。 –

+0

もちろん、膨大な量のデータを処理することはできません。 あなたが参照した質問がなぜ機能しなかったのですか? ドキュメントには、これを扱う例があります: https://ghostbin.com/paste/wt5y6 – diek

関連する問題