Время прочтения: 7 мин.

Основная цель работы – это проведение регрессионного и корреляционного анализа на основе 10000 входных данных, которые являются файлами в формате json многоуровневой вложенности.

Для начала проведения работы понадобятся следующие импортируемые библиотеки и модули Python:

import pandas as pd
import json
import glob
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn import metrics

Для удобства дальнейшей работы объединю файлы в единый табличный формат (.csv).

Начинаю с создания класса и инициализации заранее в нём необходимых переменных:

class AnalyticsDatasets:
    def __init__(self, file_name):
        self.main_path = '/home/ files/'
        self.analytics_path = '/home/analytics/'
        self.file_name = file_name
        self.main_column = 'Value'

В результате выполнения скрипта ожидаю получить файл в формате .csv, который содержит в себе 10000 строк. Добавляю метод для объединения данных в табличный формат, результат сохраняю в .csv файл:

def join_files(self, name_dir): 
    files = pd.DataFrame()
    for file in glob.glob(self.main_path + name_dir + '/*'):
        with open(file, 'r') as f:
            data_out = json.loads(f.read())
        outp = pd.io.json.json_normalize(data_out)
        outp['file'] = file
        files = files.append(outp) 
    files.to_csv(self.main_path + name_dir + '.csv',
                 encoding='utf-8', index=False)

Сформированные файлы выглядят следующим образом:

В скрипте предусмотрена многоуровневая вложенность json файлов: множественные значения преобразуются в список из значений следующего вида.

[51, 0, 0, 0]1[‘Североморск’, ‘-‘, ‘-‘, ‘-‘][’20’, ‘-‘, ‘-‘, ‘-‘]
[77, 0, 0, 0]2[‘Москва’, ‘-‘, ‘-‘, ‘-‘][‘2,115’, ‘-‘, ‘-‘, ‘-‘]
[77, 0, 0, 0]2[‘Москва’, ‘-‘, ‘-‘, ‘-‘][’89’, ‘-‘, ‘-‘, ‘-‘]

В результате обработки скрипта формируется файл с размерностью 214 столбцов и 10000 строк.

Подготовка данных

Следующим шагом является предварительная подготовка данных для дальнейшего проведения двух видов анализа, а именно регрессионного и корреляционного анализа данных.

Для этого необходимо провести ряд этапов:

1) Разделение колонок с несколькими значениями

Списки значений в колонках не подходят для дальнейшей работы. Колонки вида списка [‘N’, ‘N’, ‘N’, ‘N’] следует разделить на несколько колонок, количество которых соответствует количеству значений в списке, например:

За разделение колонок будет отвечать следующий метод:

def split_columns(self): 
    df = pd.read_csv(self.main_path + 'outputs.csv', engine='python', encoding='utf-8')
    names = list(df)
    for item in names:
        df1 = df[[item]]
        df1[item] = df1[item].astype(str).str.replace(']', '').str.replace('[','').str.replace("'",'')
        df2 = df1[item].str.split(',', expand=True)
        for name_col in list(df2):
            df2.rename(columns={name_col: item + '_' + str(name_col)}, inplace=True)
        df = pd.concat([df, df2], axis=1)
        df = df.drop(columns=[item]) 
    return df

Однако, 214 столбцов при разделении образуют 3 555 новых столбцов.

2) Предварительный программный отбор столбцов.

Для начала, данные необходимо «почистить». Дописываю в скрипт следующий метод:

def cleaning_columns(self):
    data = AnalyticsDatasets.split_columns(self) 
    data.dropna(how='all', axis=1, inplace=True)
    data = data.reset_index()
    columns_name = list(data)
    for name in columns_name[1:]:
        cl = data.groupby([name])[['index']].count()
        if len(cl['index']) == 1:
            data = data.drop(columns=[name])
    data.to_csv(self.analytics_path + 'clean_outputs_file.csv', encoding='utf-8', index=False)

По окончанию работы скрипта формируется .csv файл, содержащий 10000 строк и 590 колонок, среди которых не осталось пустых столбцов и столбцов, в которых присутствует лишь одно значение (0, nan и т.д.), ведь это не оказывает никакого влияния на другие параметры.

Перейду к последнему этапу подготовки данных.

3) Ручной отбор столбцов и кодировка значений

Для последующего анализа подходят не все образовавшиеся 590 столбцов. Чтобы не упустить нужное, было принято решение оценить их вручную. Если категориальные текстовые данные возможно закодировать в числовые данные – кодирую, если нет – столбец отбрасывается, поскольку текстовые данные не участвуют в статистических расчётах.

В итоге, были закодированы значения из 13 столбцов, а общее количество столбцов сократилось до 383, остальные – отброшены.

Теперь с уверенностью можно сказать, что данные почищены от нежелательного «мусора» и полностью подготовлены для проведения регрессионного и корреляционного анализа.

Регрессионный анализ данных

Имеется 383 колонки в файле, что соответствует наличию 383 параметрам, возможно, влияющих на ранее выделенную переменную self.main_column = ‘Value’. Теперь из этого набора данных необходимо извлечь наиболее важные параметры.

Включаем в скрипт следующие методы:

def get_attr_and_obj(self): 
    data = pd.read_excel(self.file_name)
    data.stack().apply(pd.to_numeric, errors='ignore').fillna(0).unstack()
    data = data.replace('', 0)
    data = data.fillna(0)
    names_main = list(data)
    X = data[names_main]
    Y = data[self.main_column]
    regressor = LinearRegression()
    regressor.fit(X, Y) 
    return X, Y, regressor

def get_coef_regression(self):
    X, Y, regressor = AnalyticsDatasets.get_attr_and_obj(self) 
    coef = pd.DataFrame(regressor.coef_, X.columns, columns=['coeff'])
    coef = coef.reset_index()
    coef = coef.sort_values('coeff')
    res_coef = coef[(coef['coeff'] <= -0.005) | (coef['coeff'] >= 0.005)]
    res_coef.to_csv(self.analytics_path + 'coef_regression.csv', index=False, encoding='utf-8') 
def prediction_and_score(self): 
    X, Y, regressor = AnalyticsDatasets.get_attr_and_obj(self)
    Y_pred = regressor.predict(X)
    pred_df = pd.DataFrame({'Фактические значения': Y, 'Прогнозируемые значения': Y_pred})
    pred_df.to_csv(self.analytics_path + 'prediction.csv', index=False, encoding='utf-8')
    new_row = {
       'R^2': regressor.score(X, Y),
       'Средняя абсолютная ошибка (MAE)': metrics.mean_absolute_error(Y, Y_pred),
       'Среднеквадратичная ошибка (MSE)': metrics.mean_squared_error(Y, Y_pred),
       'Среднеквадратичная ошибка (RMSE)': np.sqrt(metrics.mean_squared_error(Y, Y_pred))}

    with open(self.analytics_path + 'score.txt', 'w', encoding='utf-8') as f:
        for key, item in new_row.items():
            f.write(str(key) + ': ' + str(item) + '\n')

В результате работы скрипта формируются три файла:

  • coef_regression.csv – таблица с коэффициентами регрессии.
  • prediction.csv – первая таблица для оценки модели.
  • score.txt – вторая таблица для оценки модели.

1) Расчёт коэффициентов регрессии — файл  coef_regression.csv.

Данные имеют следующий вид:

Где в первом столбце расположены все параметры, а во втором — коэффициенты регрессии. Скрипт нам отобрал лишь те значения, которые либо меньше и равны -0.005, либо больше и равны 0.005.

Соответственно, выделен 41 параметр, которые в наибольшей степени имеют сильную взаимосвязь с исходным параметром.

2) Оценка адекватности алгоритма.

Для этого подготовлены два других файла.

А) prediction.csv – позволяет сравнить фактические выходные данные с прогнозируемыми значениями.

Получаю следующий результат:

Всего 10000 строк, соответственно, для примера выделены лишь несколько первых.

Хотя модель не очень точна, но прогнозируемые данные близки к фактическим, что говорит о адекватности данных и адекватности проведенного регрессионного анализа.

Б) score.txt  — позволяет оценить производительность алгоритма.

R-квадрат, равный 0.99, говорит о том, что примерно 99% наблюдаемых вариаций могут быть объяснены входными данными модели, что показывает высокий уровень описательной способности регрессионной модели.

Корреляционный анализ данных

Как и при регрессионном анализе проверяю влияние 384 показателей из файла на выделенную ранее переменную self.main_column = ‘Value’.

Дописываю последний метод в скрипт:

def get_correlation_coef(self): 
    corr = pd.read_excel(self.file_name)
    names_col = list(corr)
    lst_colms = []
    for item in names_col:
        try:
            corr[item] = corr[item].astype(float)
            lst_colms.append(item)
        except:
            continue
    res = corr[lst_colms]
    crl = res.corr().reset_index().sort_values(self.main_column)
    res = crl[['index', self.main_column]]
    res.dropna(subset=[self.main_column])
    result = res[(res[self.main_column] <= -0.5) | (res[self.main_column] >= 0.5)]
    result.to_csv(self.analytics_path + 'coef_corr.csv', index=False, encoding='utf-8')

Результатом выполнения скрипта является файл — coef_corr.csv, содержащий в себе восемь параметров в наибольшей степени влияющих на имеющуюся переменную.

Скриптом были отобраны лишь те параметры, коэффициенты которых больше или равно 0.5, меньше или равно -0.5, что соответствует уровню средней корреляции и выше. Таковых показателей скрипт отобрал 8.

Подводя итог, можно сказать, что основная цель в посте достигнута и все поставленные задачи были выполнены в полной мере:

  • Для удобства работы был сформирован сводный файл в табличном формате csv, собрав все данные из json файлов в компактном виде.
  • Файл с выходными данными полностью обработан: почищен от пустых столбцов, дубликатов, выбросов, нетипичных данных, неинформативных данных.
  • Проведен регрессионный и корреляционный анализ данных для выявления параметров в наибольшей степени влияющих на ранее выделенный параметр.

Количество выявленных показателей можно считать достаточным для выявления специфических особенностей.

  • Регрессионный анализ выявил 41 параметр.
  • Корреляционный анализ выявил 8 параметров.

Среди них четыре параметра встречаются в обоих результирующих таблицах.

Выполнение скрипта по обработке данных заняло 112 минут.

Удачи в кодинге!