2016-07-05 35 views
8

Mi piacerebbe trasformare da un DataFrame che contiene elenchi di parole in un DataFrame con ogni parola nella sua stessa riga.Esplodi in PySpark

Come si esplode su una colonna in un DataFrame?

Ecco un esempio con alcuni dei miei tentativi in ​​cui è possibile rimuovere il commento da ogni riga di codice e ottenere l'errore elencato nel seguente commento. Io uso PySpark in Python 2.7 con Spark 1.6.1.

from pyspark.sql.functions import split, explode 
DF = sqlContext.createDataFrame([('cat \n\n elephant rat \n rat cat',)], ['word']) 
print 'Dataset:' 
DF.show() 
print '\n\n Trying to do explode: \n' 
DFsplit_explode = (
DF 
.select(split(DF['word'], ' ')) 
# .select(explode(DF['word'])) # AnalysisException: u"cannot resolve 'explode(word)' due to data type mismatch: input to function explode should be array or map type, not StringType;" 
# .map(explode) # AttributeError: 'PipelinedRDD' object has no attribute 'show' 
# .explode() # AttributeError: 'DataFrame' object has no attribute 'explode' 
).show() 

# Trying without split 
print '\n\n Only explode: \n' 

DFsplit_explode = (
DF 
.select(explode(DF['word'])) # AnalysisException: u"cannot resolve 'explode(word)' due to data type mismatch: input to function explode should be array or map type, not StringType;" 
).show() 

Si prega di consulenza

risposta

13

explode e split sono funzioni SQL. Entrambi funzionano su SQL Column. split utilizza un'espressione regolare Java come secondo argomento. Se si vuole separare i dati su spazi arbitraria avrete bisogno di qualcosa di simile:

df = sqlContext.createDataFrame(
    [('cat \n\n elephant rat \n rat cat',)], ['word'] 
) 

df.select(explode(split(col("word"), "\s+")).alias("word")).show() 

## +--------+ 
## | word| 
## +--------+ 
## |  cat| 
## |elephant| 
## |  rat| 
## |  rat| 
## |  cat| 
## +--------+ 
6

a Split con spazi e anche rimuovere le righe vuote, aggiungere la clausola where.

DF = sqlContext.createDataFrame([('cat \n\n elephant rat \n rat cat\nmat\n',)], ['word']) 

>>> (DF.select(explode(split(DF.word, "\s")).alias("word")) 
     .where('word != ""') 
     .show()) 

+--------+ 
| word| 
+--------+ 
|  cat| 
|elephant| 
|  rat| 
|  rat| 
|  cat| 
|  mat| 
+--------+ 
+0

Grazie per la clausola where aggiunta. – user1982118

+1

Per una soluzione leggermente più completa che può essere generalizzata ai casi in cui è necessario segnalare più di una colonna, utilizzare "withColumn" invece di una semplice "selezione", ad esempio: df.withColumn ("word", explode ('word')) .show() Questo garantisce che tutte le altre colonne di DataFrame siano ancora presenti nell'FitFile di uscita, dopo aver usato explode. Ciò è anche più semplice che specificare ogni colonna che deve essere selezionata, ad esempio df.select ('col1', 'col2', ..., 'colN', esplode ('word')). Show() –