我想使用pyspark在两个spark数据帧上执行验证功能。总而言之,每个df都应该相同,并且我们通过执行多项操作(例如通过索引进行联接并计算“外部”联接中的空值,检查总和,count(),空值,非空值,不同计数)来执行验证等等,然后比较字典中给定的2行(如果一个df的寄存器多于另一个,则在内部联接之后每个df的行)。
我全部使用了应用所有本机Spark函数的函数(例如regex_replace,withColumn(F.when ....)而不是udfs-ifs等),其思想是在每列上该函数返回3个字典问题是在一个步骤中我需要遍历各列,并且当此字典(键是一个数据框的列,而值是另一个应该相同的列)时,这会花费很长时间太长了,有没有办法并行化返回字典的for循环(我不能使用df.select(....)解决方案)。
例如,用于“验证”字符串列的函数是:
def check_string(df,column):
'''
df: (pySpark dataframe) dataframe a analizar
column: (string) nombre de la columna a analizar
Returns: Diccionary with the following key:value >
total: Cantidad de registros en la columna.
nulos: Cantidad de nulos en la columna.
no_nulos: Cantidad de No nulos en la columna
distinct_count: Cantidad de valores diferentes en la columna
len_3 : cantidad de registro con Len < 3
len_3_10: Cantidad de registros con 3 < len < 10
len_10: Cantidad de registros con 10 < len
max_len: max len
min_len: min len
max_len_count: qty registros con max len
min_len_count: qty registros con min len
'''
#sqlContext.registerFunction("stringLengthString", lambda x: len(x))
total = df.count()
nulos = df.filter(F.col(column).isNull()).count()
no_nulos= total - nulos
distinct_count = df.select(column).distinct().count()
df = df.withColumn(column+'_len',F.length(column))
len_3 = df.filter(F.col(column+'_len') < 3).count()
len_3_10 = df.filter((F.col(column+'_len') > 3) & (F.col(column+'_len') <10)).count()
len_10 = df.count() - (len_3 + len_3_10)
max_len = df.select(F.max(column+'_len')).collect()[0][0]
min_len = df.select(F.min(column+'_len')).collect()[0][0]
max_len_count = df.filter(F.col(column+'_len') == max_len).count()
min_len_count = df.filter(F.col(column+'_len') == min_len).count()
return_dict = ({'columna':column,'total':total,'nulos':nulos, 'no_nulos':no_nulos, 'distinct_count':distinct_count,
'len_3':len_3,'len_3_10':len_3_10,
'len_10':len_10,'max_len':max_len,'min_len':min_len
,'max_len_count':max_len_count,'min_len_count':min_len_count})
return (return_dict)
如果列为字符串,则为十进制或日期,则存在另一个函数。
要比较我使用的列:
def comparo_columnas(df,col_1,col_2):
if df.select(col_1).dtypes[0][1] in ('string','date','int'):
df = df.withColumn('comparison_'+col_1,F.when(F.col(col_1)==F.col(col_2),1).otherwise(0))
else:
df = df.withColumn('comparison_'+col_1,F.when(abs(F.col(col_1)-F.col(col_2))<0.05,1).otherwise(0))
total_igual = df.filter(F.col('comparison_'+col_1)==1).count()
tot_dif = df.filter(F.col('comparison_'+col_1)==0).count()
return({'columna':col_1,'registros_iguales':total_igual,'registros_diferentes':tot_dif})
这个想法是只有一个函数占用2 df的空间,并且有一个字典列,执行几个这样的函数,然后保存这些字典。有没有一种方法可以优化列的for循环?我看过类似的页面 https://medium.com/@mrpowers/performing-operations-on-multiple-columns-in-a-pyspark-dataframe-36e97896c378 但是它们都优化了返回数据帧的函数,我不知道如何应用它们。
先谢谢您,如果我的英语不是最好的话!