繁体   English   中英

从 Spark dataframe 上的 pandas 执行预处理操作

[英]Perform preprocessing operations from pandas on Spark dataframe

我有一个相当大的 CSV 所以我使用 AWS EMR 将数据读入 Spark dataframe 以执行一些操作。 我有一个 pandas function 可以进行一些简单的预处理:

def clean_census_data(df):
    """
    This function cleans the dataframe and drops columns that contain 70% NaN values
    """
    # Replace None or 0 with np.nan
    df = df.replace('None', np.nan)
    # Replace weird numbers
    df = df.replace(-666666666.0, np.nan)
    
    # Drop columns that contain 70% NaN or 0 values
    df = df.loc[:, df.isnull().mean() < .7]
    
    
    return df

我想将此 function 应用到 Spark dataframe 上,但功能不一样。 我不熟悉 Spark,在 pandas 中执行这些相当简单的操作对我来说如何在 Spark 中执行相同的操作并不明显。 我知道我可以将 Spark dataframe 转换为 pandas,但这似乎不是很有效。

第一次回答,请善待。 这个 function 应该与 pyspark 数据帧而不是 pandas 数据帧一起使用,并且应该给你类似的结果:

def clean_census_data(df):
    """
    This function cleans the dataframe and drops columns that contain 70% NaN values
    """
    # Replace None or 0 with np.nan
    df = df.replace('None', None)

    # Replace weird numbers
    df = df.replace(-666666666.0, None)

    # Drop columns that contain 70% NaN or 0 values
    selection_dict = df.select([(count(when(isnan(c) | col(c).isNull() | (col(c).cast('int') == 0), c))/count(c) > .7).alias(c) for c in df.columns]).first().asDict()
    columns_to_remove = [name for name, is_selected in selection_dict.items() if is_selected]
    df = df.drop(*columns_to_remove)

    return df

注意:生成的 dataframe 包含 None 而不是 np.nan。

原生 Spark 函数可以对每一列进行这种聚合。
以下 dataframe 包含空值、nans 和零的百分比。

df2 = df1.select(
    [(F.count(F.when(F.isnan(c) | F.isnull(c) | (F.col(c) == 0), c))
     / F.count(F.lit(1))).alias(c) 
     for c in df1.columns]
)

举个例子:

from pyspark.sql import functions as F
df1 = spark.createDataFrame(
    [(1000, 0, None),
     (None, 2, None),
     (None, 3, 2222),
     (None, 4, 2233),
     (None, 5, 2244)],
    ['c1', 'c2', 'c3'])

df2 = df1.select(
    [(F.count(F.when(F.isnan(c) | F.isnull(c) | (F.col(c) == 0), c))
     / F.count(F.lit(1))).alias(c) 
     for c in df1.columns]
)
df2.show()
# +---+---+---+
# | c1| c2| c3|
# +---+---+---+
# |0.8|0.2|0.4|
# +---+---+---+

剩下的只是从 df1 中选择列:

df = df1.select([c for c in df1.columns if df2.head()[c] < .7])
df.show()
# +---+----+
# | c2|  c3|
# +---+----+
# |  0|null|
# |  2|null|
# |  3|2222|
# |  4|2233|
# |  5|2244|
# +---+----+

百分比是根据这个条件计算的,根据你的需要改变它:
F.isnan(c) | F.isnull(c) | (F.col(c) == 0)

这将用 np.nan 替换 None :
df.fillna(np.nan)

这将用 np.nan 替换指定的值:
df.replace(-666666666, np.nan)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM