Pandas Correlation - Обработка нулей в обеих колонках - PullRequest
0 голосов
/ 24 октября 2019

Ситуация: Я работаю с большим фреймом данных, около 100 столбцов и около 2 миллионов строк. Цель состоит в том, чтобы найти корреляцию между каждым столбцом. Но в наборе данных есть много значений 0 в каждой строке, поэтому, когда я использую df.corr(), результат будет неправильным, потому что корреляция между двумя строками, допустим, A и B, с большим количеством (0, 0), имеет другую форму (x, y), для x != 0 | y != 0.

Примерно так:

#dataframe without zeros for both columns
df = pd.Dataframe([(.2, .3), (.1, .2), (.3, .6), (.6, .9), 
    (.5, .0), (.0, .5)], columns = ['dogs', 'cats'])
ρ = corr(dogs,cats) = 0.2482

#dataframe with lots of zeros for both columns
df = pd.Dataframe([(.2, .3), (.1, .2), (.3, .6), (.6, .9), 
    (.5, .0), (.0, .5), (.0, .0), (.0, .0), (.0, .0), (.0, .0)],
    columns = ['dogs', 'cats'])
ρ = corr(dogs,cats) = 0.5743

#dataframe with np.NaN instead of every zero
df = pd.Dataframe([(.2, .3), (.1, .2), (.3, .6), (.6, .9), 
    (.5, .0), (.0, .5), (.0, .0), (.0, .0), (.0, .0), (.0, .0)],
    columns = ['dogs', 'cats'])
df = df.replace(0, np.NaN)
ρ = corr(dogs,cats) = 0.9759

Основная проблема: Использование NaN при расчете корреляции в pandas df подразумевает, что он будет игнорировать все наборы, которые имеютхотя бы один ноль, поэтому df становится: [(.2, .3), (.1, .2), (.3, .6), (.6, .9)]. Мне нужно вычислить корреляцию без (0, 0), но с (0,y) & (x, 0), и в настоящее время единственный возможный способ, который я могу изобразить, - построить два цикла for и выполнить итерации по каждому столбцу ...

Например:

results = []
for (col_name_1, col_data_1) in df.iteritems():
    for (col_name_2, col_data_2) in df.iteritems():          
        res = pd.concat([col_data_1, col_data_2])

        #only get the rows that aren't (0,0)
        res = res[!((res[col_name_1] == 0) & (res[col_name_2] == 0))]

        #get the value from the correlation and save it
        corr = result.corr().stack()[1]
        results.append((col_name_1, col_data_2, corr,))

РЕДАКТИРОВАТЬ Просто чтобы прояснить ситуацию, теперь, когда я использую df.corr () без циклов for, это занимает 1 минуту. С помощью цикла for, представленного выше, процесс начался более 30 минут назад и все еще выполняется. Может быть, я должен перейти к пустому столбцу каждого столбца df, чтобы выполнить операцию ...

Ответы [ 2 ]

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

Да! Это работает намного лучше, когда я изменяю df на пустой массив для выполнения вычислений. Он изменился с более 1 часа с пандами до менее 1 минуты с NumPy. Важно отметить , что с pandas.corr () он работает довольно быстро, потому что pandas построен поверх NumPy. Проблема заключалась во всех этих манипуляциях с данными для расчета корреляции для каждой пары.

Итоговый код:

corr_np = corr_df.to_numpy()  
correlations = []

print('{} - Calculating Correlation'.format(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))

for col_1 in range(corr_np.shape[-1]):
    for col_2 in range(corr_np.shape[-1]):
        if col_2 > col_1: #to not calculate duplicates, eg. (A, G) (G, A)
            # to remove rows when both are 0, eg. (0, 0)
            numpy_col_1 = corr_np[~((corr_np[:,col_1]==.0) & (corr_np[:,col_2]==.0)),col_1]
            numpy_col_2 = corr_np[~((corr_np[:,col_1]==.0) & (corr_np[:,col_2]==.0)),col_2]
            cor = np.corrcoef(numpy_col_1, numpy_col_2)[-1,0]
            correlations.append(cor)

print('{} -\t Finished'.format(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))

Вывод:

2019-10-24 hh:19:50 - Calculating Correlation
2019-10-24 hh:20:30 -    Finished
0 голосов
/ 24 октября 2019

Это то, чего вы хотите достичь:

df[~((df.dogs==0.0)&(df.cats==0.0))].corr()
    dogs    cats
dogs    1.000000    0.248199
cats    0.248199    1.000000

или, если хотите,

rho = df[~((df.dogs==0.0)&(df.cats==0.0))].corr().iloc[1,0]
rho
0.24819888822736433
...