Корреляция в Apache Spark и groupBy с Python - PullRequest
0 голосов
/ 27 октября 2019

Я новичок в Python и Apache Spark и пытаюсь понять, как работает функция "pyspark.sql.functions.corr (val1, val2)".

У меня большой массив данных с автобрендом,возраст и цена. Я хочу получить корреляцию между возрастом и ценой для каждой автомобильной марки.

У меня есть 2 решения:

//get all brands    
get_all_maker = data.groupBy("brand").agg(F.count("*").alias("counts")).collect()

for row in get_all_maker:
    print(row["brand"],": ",data.filter(data["brand"]==row["brand"]).corr("age","price"))

Это решение медленное, потому что я часто использую "corr".

Поэтому я попытался сделать это с одной агрегацией:

get_all_maker_corr = data.groupBy("brand").agg(
    F.count("*").alias("counts"),
    F.corr("age","price").alias("correlation")).collect()

for row in get_all_maker_corr:
    print(row["brand"],": ",row["correlation"])

Если я попытаюсь сравнить результаты, они будут разными. Но почему?

1 Ответ

0 голосов
/ 27 октября 2019

Я пробовал на простых примерах. Здесь я генерирую простой фрейм данных:

d = [
    {'name': 'a', 'age': 1, 'price': 2},
    {'name': 'a', 'age': 2, 'price': 4},

    {'name': 'b', 'age': 1, 'price': 1},
    {'name': 'b', 'age': 2, 'price': 2}
]
b = spark.createDataFrame(d)

Давайте проверим два метода:

#first version
get_all_maker = b.groupBy("name").agg(F.count("*").alias("counts")).collect()

print("Correlation (1st)") 
for row in get_all_maker:
    print(row["name"],"(",row["counts"],"):",b.filter(b["name"] == row["name"]).corr("age","price"))

#second version
get_all_maker_corr = b.groupBy("name").agg(
    F.count("*").alias("counts"),
    F.corr("age","price").alias("correlation")).collect()

print("Correlation (2nd)") 

for row in get_all_maker_corr:
    print(row["name"],"(",row["counts"],"):",row["correlation"])

Оба они дают мне один и тот же ответ:

Correlation (1st)
b ( 2 ): 1.0
a ( 2 ): 1.0

Давайте добавимдругая запись во фрейм данных со значением None:

d = [
    {'name': 'a', 'age': 1, 'price': 2},
    {'name': 'a', 'age': 2, 'price': 4},
    {'name': 'a', 'age': 3, 'price': None},

    {'name': 'b', 'age': 1, 'price': 1},
    {'name': 'b', 'age': 2, 'price': 2}
]
b = spark.createDataFrame(d)

В первой версии вы получите следующие результаты:

Correlation (1st)
b ( 2 ): 1.0
a ( 3 ): -0.5

, а во второй версии вы получите другие результаты:

Correlation (2nd)
b ( 2 ): 1.0
a ( 3 ): 1.0

Я думаю, что dataframe.filter с функцией corr установил None-value в значение 0.

И dataframe.groupBy с F.corr-функцией в agg-функции будет игнорировать None-value.

Итак, два этих метода не равны. Я не знаю, если это ошибка или особенность системы Spark, но на случай, если вы хотите посчитать значение корреляции, данные должны использоваться только без значения None.

...