Использовать Dask для удаления высококоррелированных парных функций в Dataframe? - PullRequest
1 голос
/ 09 июля 2020

Трудно найти пример этого, но я бы хотел каким-то образом использовать Dask для удаления попарно коррелированных столбцов, если их порог корреляции выше 0,99. Я НЕ МОГУ использовать функцию Pandas 'correlation, так как мой набор данных слишком велик, и он в спешке съедает мою память. То, что у меня сейчас, - это медленный двойной for l oop, который начинается с первого столбца и находит порог корреляции между ним и всеми другими столбцами один за другим, и если он выше 0,99, отбросьте этот второй сравнительный столбец , затем начинается с нового второго столбца и так далее, и так далее, ВИД, как решение , найденное здесь , однако это невыносимо медленно, выполняя это в итеративной форме для всех столбцов, хотя на самом деле это возможно запустите его и не столкнитесь с проблемами памяти.

Я прочитал API здесь и посмотрел, как удалить столбцы с помощью Dask здесь , но мне нужна помощь в понять это. Мне интересно, есть ли более быстрый, но дружелюбный к памяти способ удаления сильно коррелированных столбцов в Pandas Dataframe с помощью Dask? Я хотел бы передать в функцию фрейм данных Pandas, чтобы он возвращал фрейм данных Pandas после завершения корреляции.

У кого-нибудь есть ресурсы, которые я могу проверить, или есть пример того, как это сделать?

Спасибо!

ОБНОВЛЕНИЕ По запросу, вот моя текущая процедура удаления корреляции, как описано выше:

print("Checking correlations of all columns...")

cols_to_drop_from_high_corr = []
corr_threshold = 0.99

for j in df.iloc[:,1:]:  # Skip column 0

    try:  # encompass the below in a try/except, cuz dropping a col in the 2nd 'for' loop below will screw with this
        # original list, so if a feature is no longer in there from dropping it prior, it'll throw an error

        for k in df.iloc[:,1:]:  # Start 2nd loop at first column also...

            # If comparing the same column to itself, skip it
            if (j == k):  
                continue

            else:
                try: # second try/except mandatory
                    correlation = abs(df[j].corr(df[k]))  # Get the correlation of the first col and second col

                    if correlation > corr_threshold:  # If they are highly correlated...
                        cols_to_drop_from_high_corr.append(k)  # Add the second col to list for dropping when round is done before next round.")
                
                except:
                    continue

        # Once we have compared the first col with all of the other cols...
        if len(cols_to_drop_from_high_corr) > 0:
            df = df.drop(cols_to_drop_from_high_corr, axis=1)  # Drop all the 2nd highly corr'd cols
            cols_to_drop_from_high_corr = [] # Reset the list for next round
            # print("Dropped all cols from most recent round. Continuing...")

    except:  # Now, if the first for loop tries to find a column that's been dropped already, just continue on
        continue

print("Correlation dropping completed.")

ОБНОВЛЕНИЕ Используя приведенное ниже решение, я столкнулся с несколькими ошибками, и из-за моих ограниченных знаний синтаксиса dask я надеюсь получить некоторое представление. Запустив Windows 10, Python 3.6 и последнюю версию dask.

Используя код как есть в МОЕМ наборе данных (в наборе данных в ссылке написано «файл не найден»), я столкнулся с первым ошибка:

ValueError: Exactly one of npartitions and chunksize must be specified.

Поэтому я указываю npartitions=2 в from_pandas, а затем получаю эту ошибку:

AttributeError: 'Array' object has no attribute 'compute_chunk_sizes'

Я попытался изменить это на .rechunk('auto'), но затем получил ошибку :

ValueError: Can not perform automatic rechunking with unknown (nan) chunk sizes

Мой исходный фрейм данных имеет форму 1275 строк и 3045 столбцов. Форма массива dask говорит shape = (nan, 3045). Помогает ли это вообще диагностировать проблему?

1 Ответ

2 голосов
/ 10 июля 2020

Я не уверен, поможет ли это, но, возможно, это может быть отправной точкой.

Pandas

import pandas as pd
import numpy as np

url = "https://raw.githubusercontent.com/dylan-profiler/heatmaps/master/autos.clean.csv"

df = pd.read_csv(url)

# we check correlation for these columns only
cols = df.columns[-8:]

# columns in this df don't have a big 
# correlation coefficient
corr_threshold = 0.5

corr = df[cols].corr().abs().values

# we take the upper triangular only
corr = np.triu(corr)

# we want high correlation but not diagonal elements
# it returns a bool matrix
out = (corr != 1) & (corr > corr_threshold)

# for every row we want only the True columns
cols_to_remove = []
for o in out:
    cols_to_remove += cols[o].to_list()

cols_to_remove = list(set(cols_to_remove))

df = df.drop(cols_to_remove, axis=1)

Dask

Здесь я комментирую только шаги отличаются от pandas

import dask.dataframe as dd
import dask.array as da

url = "https://raw.githubusercontent.com/dylan-profiler/heatmaps/master/autos.clean.csv"

df = dd.read_csv(url)

cols = df.columns[-8:]

corr_threshold = 0.5

corr = df[cols].corr().abs().values

# with dask we need to rechunk
corr = corr.compute_chunk_sizes()

corr = da.triu(corr)

out = (corr != 1) & (corr > corr_threshold)

# dask is lazy
out = out.compute()

cols_to_remove = []
for o in out:
    cols_to_remove += cols[o].to_list()

cols_to_remove = list(set(cols_to_remove))

df = df.drop(cols_to_remove, axis=1)

...