Je suis nouveau spark et python et je suis confronté à cette difficulté de construction d'un schéma à partir d'un fichier de métadonnées qui peut être appliqué à mon fichier de données. Scénario: Fichier de métadonnées pour le fichier Data (format csv), contient les colonnes et leurs types: par exemple:
id,int,10,"","",id,"","",TRUE,"",0
created_at,timestamp,"","","",created_at,"","",FALSE,"",0
J'ai réussi à convertir cela en une trame de données qui ressemble à:
+--------------------+---------------+
| name| type|
+--------------------+---------------+
| id| IntegerType()|
| created_at|TimestampType()|
| updated_at| StringType()|
Mais quand j'essaie de convertir cela en un format StructField en utilisant ce
fields = schemaLoansNew.map(lambda l:([StructField(l.name, l.type, 'true')]))
OR
schemaList = schemaLoansNew.map(lambda l: ("StructField(" + l.name + "," + l.type + ",true)")).collect()
Et ensuite, convertissez-le en StructType, en utilisant
schemaFinal = StructType(schemaList)
J'obtiens l'erreur suivante:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/mapr/spark/spark-1.4.1/python/pyspark/sql/types.py", line 372, in __init__
assert all(isinstance(f, DataType) for f in fields), "fields should be a list of DataType"
AssertionError: fields should be a list of DataType
Je suis coincé à ce sujet en raison de mon manque de connaissances sur les trames de données, pouvez-vous s'il vous plaît indiquer comment procéder à ce sujet. une fois le schéma prêt, je souhaite utiliser createDataFrame pour appliquer à mon fichier de données. Ce processus doit être fait pour de nombreuses tables, donc je ne veux pas coder en dur les types plutôt utiliser le fichier de métadonnées pour construire le schéma et ensuite appliquer au RDD.
Merci d'avance.
Les champs dont l'argument doit être une liste d'objets DataType
. Cette:
.map(lambda l:([StructField(l.name, l.type, 'true')]))
génère après collect
a list
de lists
de tuples
(Rows
) de DataType
(list[list[Tuple[DataType]]]
) sans mentionner que l'argument nullable
doit être booléen et non une chaîne.
Votre deuxième tentative:
.map(lambda l: ("StructField(" + l.name + "," + l.type + ",true)")).
génère après collect
un list
des str
objets.
Le schéma correct pour l'enregistrement que vous avez montré devrait ressembler plus ou moins à ceci:
from pyspark.sql.types import *
StructType([
StructField("id", IntegerType(), True),
StructField("created_at", TimestampType(), True),
StructField("updated_at", StringType(), True)
])
Bien que l'utilisation de structures de données distribuées pour une tâche comme celle-ci soit une exagération grave, sans parler de l'inefficacité, vous pouvez essayer d'ajuster votre première solution comme suit:
StructType([
StructField(name, eval(type), True) for (name, type) in df.rdd.collect()
])
mais ce n'est pas particulièrement sûr (eval
). Il pourrait être plus facile de créer un schéma à partir de JSON/dictionnaire. En supposant que vous ayez une fonction qui mappe de la description de type au nom de type canonique:
def get_type_name(s: str) -> str:
"""
>>> get_type_name("int")
'integer'
"""
_map = {
'int': IntegerType().typeName(),
'timestamp': TimestampType().typeName(),
# ...
}
return _map.get(s, StringType().typeName())
Vous pouvez créer un dictionnaire de la forme suivante:
schema_dict = {'fields': [
{'metadata': {}, 'name': 'id', 'nullable': True, 'type': 'integer'},
{'metadata': {}, 'name': 'created_at', 'nullable': True, 'type': 'timestamp'}
], 'type': 'struct'}
et le nourrir à StructType.fromJson
:
StructType.fromJson(schema_dict)
val columns: Array[String] = df1.columns
val reorderedColumnNames: Array[String] = df2.columns //or do the reordering you want
val result: DataFrame = dataFrame.select(reorderedColumnNames.head, reorderedColumnNames.tail: _*)
Les étapes ci-dessous peuvent être suivies pour modifier les objets de type de données
data_schema=[
StructField("age", IntegerType(), True),
StructField("name", StringType(), True)
]
final_struct=StructType(fields=data_schema)
df=spark.read.json('/home/abcde/Python-and-Spark-for-Big-Data-master/Spark_DataFrames/people.json', schema=final_struct)
df.printSchema()
root
|-- age: integer (nullable = true)
|-- name: string (nullable = true)