Ich habe es mit ziemlich großen Pandas DataFrame zu tun - mein Datensatz ähnelt einem folgenden df
Setup:
import pandas as pd
import numpy as np
#--------------------------------------------- SIZING PARAMETERS :
R1 = 20 # .repeat( repeats = R1 )
R2 = 10 # .repeat( repeats = R2 )
R3 = 541680 # .repeat( repeats = [ R3, R4 ] )
R4 = 576720 # .repeat( repeats = [ R3, R4 ] )
T = 55920 # .tile( , T)
A1 = np.arange( 0, 2708400, 100 ) # ~ 20x re-used
A2 = np.arange( 0, 2883600, 100 ) # ~ 20x re-used
#--------------------------------------------- DataFrame GENERATION :
df = pd.DataFrame.from_dict(
{ 'measurement_id': np.repeat( [0, 1], repeats = [ R3, R4 ] ),
'time':np.concatenate( [ np.repeat( A1, repeats = R1 ),
np.repeat( A2, repeats = R1 ) ] ),
'group': np.tile( np.repeat( [0, 1], repeats = R2 ), T ),
'object': np.tile( np.arange( 0, R1 ), T )
}
)
#--------------------------------------------- DataFrame RE-PROCESSING :
df = pd.concat( [ df,
df \
.groupby( ['measurement_id', 'time', 'group'] ) \
.apply( lambda x: np.random.uniform( 0, 100, 10 ) ) \
.explode() \
.astype( 'float' ) \
.to_frame( 'var' ) \
.reset_index( drop = True )
], axis = 1
)
Hinweis: Um ein minimales Beispiel zu haben, kann es leicht untergeordnet werden (zum Beispiel mit df.loc[df['time'] <= 400, :]
), aber da ich die Daten trotzdem simuliere, dachte ich, dass die Originalgröße einen besseren Überblick geben würde.
Für jede von definierte Gruppe muss ['measurement_id', 'time', 'group']
ich die folgende Funktion aufrufen:
from sklearn.cluster import SpectralClustering
from pandarallel import pandarallel
def cluster( x, index ):
if len( x ) >= 2:
data = np.asarray( x )[:, np.newaxis]
clustering = SpectralClustering( n_clusters = 5,
random_state = 42
).fit( data )
return pd.Series( clustering.labels_ + 1, index = index )
else:
return pd.Series( np.nan, index = index )
Um die Leistung zu verbessern, habe ich zwei Ansätze ausprobiert:
Pandarallel-Paket
Der erste Ansatz bestand darin, die Berechnungen mit dem pandarallel
Paket zu parallelisieren :
pandarallel.initialize( progress_bar = True )
df \
.groupby( ['measurement_id', 'time', 'group'] ) \
.parallel_apply( lambda x: cluster( x['var'], x['object'] ) )
Dies scheint jedoch nicht optimal zu sein, da es viel RAM verbraucht und nicht alle Kerne für Berechnungen verwendet werden (obwohl die Anzahl der Kerne in der pandarallel.initialize()
Methode explizit angegeben wurde ). Manchmal werden Berechnungen auch mit verschiedenen Fehlern beendet, obwohl ich keine Gelegenheit hatte, einen Grund dafür zu finden (möglicherweise ein Mangel an RAM?).
PySpark Pandas UDF
Ich habe auch einen Spark Pandas UDF ausprobiert, obwohl ich für Spark völlig neu bin. Hier ist mein Versuch:
import findspark; findspark.init()
from pyspark.sql import SparkSession
from pyspark.conf import SparkConf
from pyspark.sql.functions import pandas_udf, PandasUDFType
from pyspark.sql.types import *
spark = SparkSession.builder.master( "local" ).appName( "test" ).config( conf = SparkConf() ).getOrCreate()
df = spark.createDataFrame( df )
@pandas_udf( StructType( [StructField( 'id', IntegerType(), True )] ), functionType = PandasUDFType.GROUPED_MAP )
def cluster( df ):
if len( df['var'] ) >= 2:
data = np.asarray( df['var'] )[:, np.newaxis]
clustering = SpectralClustering( n_clusters = 5,
random_state = 42
).fit( data )
return pd.DataFrame( clustering.labels_ + 1,
index = df['object']
)
else:
return pd.DataFrame( np.nan,
index = df['object']
)
res = df \
.groupBy( ['id_half', 'frame', 'team_id'] ) \
.apply( cluster ) \
.toPandas()
Leider war auch die Leistung unbefriedigend, und nach dem, was ich zu diesem Thema gelesen habe, ist dies möglicherweise nur die Belastung durch die Verwendung der in Python geschriebenen UDF-Funktion und die damit verbundene Notwendigkeit, alle Python-Objekte in Spark-Objekte und zurück zu konvertieren.
Also hier sind meine Fragen:
- Könnte einer meiner Ansätze angepasst werden, um mögliche Engpässe zu beseitigen und die Leistung zu verbessern? (zB PySpark-Setup, Anpassen nicht optimaler Operationen usw.)
- Sind sie bessere Alternativen? Wie vergleichen sie sich hinsichtlich der Leistung mit den angebotenen Lösungen?
dask
(((mein Kommentar ist also nur ein Ratschlag für die Forschung)