Trabajo en un marco de datos con dos columnas, mvv y count.
+---+-----+
|mvv|count|
+---+-----+
| 1 | 5 |
| 2 | 9 |
| 3 | 3 |
| 4 | 1 |
Me gustaría obtener dos listas que contengan valores mvv y valor de recuento. Algo como
mvv = [1,2,3,4]
count = [5,9,3,1]
Entonces, probé el siguiente código: La primera línea debería devolver una lista de filas de Python. Quería ver el primer valor:
mvv_list = mvv_count_df.select('mvv').collect()
firstvalue = mvv_list[0].getInt(0)
Pero recibo un mensaje de error con la segunda línea:
AttributeError: getInt
python
apache-spark
pyspark
spark-dataframe
a.moussa
fuente
fuente
list(df.select('mvv').toPandas()['mvv'])
. Arrow se integró en PySpark, lo que acelerótoPandas
significativamente. No use los otros enfoques si está usando Spark 2.3+. Consulte mi respuesta para obtener más detalles sobre la evaluación comparativa.Respuestas:
Mira, por qué esta forma en que lo estás haciendo no funciona. Primero, está tratando de obtener un número entero de un tipo de fila , el resultado de su recopilación es así:
Si toma algo como esto:
Obtendrás el
mvv
valor. Si desea toda la información de la matriz, puede tomar algo como esto:Pero si intentas lo mismo para la otra columna, obtienes:
Esto sucede porque
count
es un método incorporado. Y la columna tiene el mismo nombre quecount
. Una solución alternativa para hacer esto es cambiar el nombre de la columna decount
a_count
:Pero esta solución alternativa no es necesaria, ya que puede acceder a la columna utilizando la sintaxis del diccionario:
¡Y finalmente funcionará!
fuente
select('count')
uso de esta manera:count_list = [int(i.count) for i in mvv_list.collect()]
agregaré el ejemplo a la respuesta.[i.['count'] for i in mvv_list.collect()]
trabajos para que sea explícita para usar la columna denominada 'contar' y no a lacount
funciónSeguir un trazador de líneas le da la lista que desea.
fuente
Esto le dará todos los elementos como una lista.
fuente
El siguiente código te ayudará
fuente
En mis datos obtuve estos puntos de referencia:
0,52 segundos
0.271 segundos
0.427 segundos
El resultado es el mismo
fuente
toLocalIterator
lugar decollect
, debería ser incluso más eficiente en la memoria[row[col] for row in data.toLocalIterator()]
Si recibe el siguiente error:
Este código resolverá sus problemas:
fuente
Ejecuté un análisis comparativo y
list(mvv_count_df.select('mvv').toPandas()['mvv'])
es el método más rápido. Estoy muy sorprendido.Ejecuté los diferentes enfoques en 100 mil / 100 millones de conjuntos de datos de filas utilizando un clúster i3.xlarge de 5 nodos (cada nodo tiene 30,5 GB de RAM y 4 núcleos) con Spark 2.4.5. Los datos se distribuyeron uniformemente en 20 archivos Parquet comprimidos y ágiles con una sola columna.
Estos son los resultados de la evaluación comparativa (tiempos de ejecución en segundos):
Reglas de oro a seguir al recopilar datos en el nodo del controlador:
toPandas
se mejoró significativamente en Spark 2.3 . Probablemente no sea el mejor enfoque si está utilizando una versión Spark anterior a la 2.3.Consulte aquí para obtener más detalles / resultados de evaluación comparativa.
fuente
Una posible solución es usar la
collect_list()
función depyspark.sql.functions
. Esto agregará todos los valores de columna en una matriz pyspark que se convierte en una lista de Python cuando se recopila:fuente