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

В настоящее время большинство задач, связанных с обработкой таблиц, выполняются на Python с использованием библиотеки Pandas. Но в некоторых случаях рационально использовать другой язык программирования. Тогда на помощь придет C# и библиотека Deedle для работы с Dataframe. Рассмотрю часть возможных методов работы с Dataframe.

            Создание Dataframe

Довольно часто, при работе с таблицами, приходится считывать информацию из файла. В данном случае, библиотека позволяет создать Dataframe, считав информацию из csv-файла. Это можно сделать с помощью метода ReadCsv.

Полученный Dataframe, после считывания данных из файла и вывода их на экран, представлен на рисунке 1.

// путь к файлу
string path_file = @"C:\Users\Admin\Desktop\Калорийность.csv";
// считываем таблицу в dataframe
Frame<int, string> df = Frame.ReadCsv(location: path_file, hasHeaders:true, inferTypes: false, separators: ";", maxRows: 10);
df.Print();
Рисунок 1. Dataframe из csv-файла.

Метод ReadCsv принимает на вход достаточно много параметров. Рассмотрю некоторые из них:

  • location  — задает путь к файлу;
  • hasHeaders – определяет, есть ли в таблице названия колонок. Если значение true, тогда заголовки считываются из первой строки. Значение по умолчанию – true;
  • inferTypes – задает, нужно ли определять автоматически типы данных в столбцах;
  • separators – задает разделитель для столбцов;
  • maxRows – задает максимальное количество строк для загрузки из файла.

Стоит отметить, что если csv-файл содержал кириллицу и кодировка текста была не UTF-8, то при чтении данных из файла могут возникнуть проблемы.

Еще один способ создания Dataframe – создание таблицы из уже имеющихся данных. Предположим, у нас есть двумерный массив с данными (lines) и лист (list_colomns), который содержит названия колонок. Range задает стартовый индекс в Dataframe и количество строк. Далее необходимо представить каждую строку объектом Series и заполнить ее данными. Метод Add добавляет значение каждой колонки последовательно в объект Series, а после создается пара ключ-значение, где ключ – это индекс строки (переменная i), а значение – это строка в виде объекта Series. После всех действий создать Dataframe можно с помощью FromRows.

// задается диапазон строк
var rows = Enumerable.Range(0, 100).Select(i =>
                {
			// создается объект Series для строки
                    var seriesBuild = new SeriesBuilder<string>();
                    for (int j = 0; j < list_colomns.Count; j++)
                    {
			    // добавляется значение колонки для строки
                        seriesBuild.Add(list_colomns [j], lines[i][j]);
                    }
                    return KeyValue.Create(i, seriesBuild.Series);
                });
// создается dataframe из строк
var df = Frame.FromRows(rows);

Работа со столбцами и строками

Чтобы посчитать количество колонок Dataframe можно использовать несколько способов, которые представлены ниже. Для подсчета количества строк можно использовать метод RowCount:

// подсчет количества колонок
int count_colomns = df.ColumnCount;
int count_colomns_1 = df.Columns.KeyCount;

// получение количества строк
int count_rows = df.RowCount;

Чтобы получить список наименований колонок, буду использовать метод ColumnKeys. Для дальнейшей работы с именами колонок можно преобразовать полученный объект в массив или список. Подобным образом можно получить список индексов строк Dataframe, используя метод RowKeys. Получить индексы строк будет актуально в том случае, когда индексация начиналась не с нуля, или индексы были не целыми числами.

// получение названия колонок
string[] colomn_names_array = df.ColumnKeys.ToArray();
List<string> colomn_names_1 = df.ColumnKeys.ToList();

// получение индексов строк
int[] rows_index_array = df.RowKeys.ToArray();
List<int> rows_index_list = df.RowKeys.ToList();

Если нужно получить значения конкретного столбца, то нужно использовать метод GetColumn и далее указать название колонки или обратиться к колонке по ее имени, используя свойство Columns. В обоих случаях получаю объект Series, и обращаться к каждому элементу колонки можно по индексу или с помощью метода GetAt.

// получение колонки ПРОДУКТ
var colomn = df.GetColumn<string>("ПРОДУКТ");
var colomn_1 = df.Columns["ПРОДУКТ"];
// получение первого значения из колонки ПРОДУКТ
string value_0 = colomn[0];
string value_6 = colomn_1.GetAt(6);

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

// получение значения столбца ПРОДУКТ
List<string> list_col = df.GetColumn<string>("ПРОДУКТ").GetAllValues().ToList()

Чтобы получить строку Dataframe буду использовать метод GetRowAt, указывая далее индекс строки. Он возвращает строку в виде объекта Series. Чтобы обратиться к элементу строки указываем в скобках название столбца в кавычках.

// получение строки по индексу
var string_df = df.GetRowAt<string>(0);
// получение значения из столбца БЕЛКИ
var value_1 = string_df["БЕЛКИ"];

Если мы нет уверенности, что в Dataframe есть нужная колонка или строка, то это можно проверить с помощью методов TryGetColumn и TryGetRow. Для TryGetColumn указывается название колонки, которую необходимо получить, а также способ поиска названия колонки. В данном случае указан точный поиск названия колонки. Для TryGetRow указывается индекс строки, которую необходимо найти. Результатом поиска колонки или строки будет объект Series.

// получение колонки ККАЛ
var try_colomn = df.TryGetColumn<string>("ККАЛ", Lookup.Exact);

// получение строки с индексом 10
var try_row = df.TryGetRow<string>(10);

Иногда возникает необходимость в преобразовании данных из одного типа в другой. Это можно сделать с помощью метода GetAs. Выбор столбца, потом самого метода, указывается тип, к которому нужно привести значение, и в конце индекс элемента.

// преобразование элемента из одного типа в другой
double value_ = df.Columns["БЕЛКИ"].GetAs<double>(0);

Переименовать колонку можно с помощью метода RenameColumn, указав старое название колонки и новое.

// переименование колонки ПРОДУКТ
df.RenameColumn("ПРОДУКТ", "Наименование продукта");

Для добавления новой колонки в Dataframe нужно сначала создать объект Series, а потом добавить его в нужную таблицу. Объект Series создаю из листа, содержащего нужные значения, подобно тому, как создавали Dataframe из строк. Только в данном случае при создании пар ключ-значение ключом будет индекс строки, а значением – данные, которые будем записывать в ячейку нового столбца.

Результат добавления нового столбца в таблицу представлен на рисунке 2

// список значений для новой колонки
List<string> list_new_col = new List<string>() { "260", "51", "30", "59", "58", "83", "475", "135", "315", "58"};
// создание объекта Series из списка
var new_colomn = Enumerable.Range(0, 10).Select(i => 
                KeyValue.Create(i, list_new_col[i])).ToSeries();
// добавление колонки в Dataframe
df.AddColumn("ККАЛ", new_colomn);
df.Print();
Рисунок 2. Результат добавления столбца в таблицу.

Также новый столбец можно добавить в таблицу, получив его в ходе вычислений, основанных на уже существующем столбце. Для этого выбираю столбец, применяю метод SelectValues и пишу функцию, которая сформирует значения для нового столбца.

На рисунке 3 представлен результат вычисления нового столбца на основе существующего.

df["ККАЛ на 1 грамм белка"] = df.GetColumn<string>("БЕЛКИ").SelectValues<double>(
                (x) =>
                {
                    return Convert.ToDouble(x) * 4;
                });
Рисунок 3. Вычисление нового столбца

Удаление колонки из Dataframe можно выполнить с использованием метода DropColumn. Он позволяет удалить колонку по ее названию.

На рисунке 4 результат удаления колонки «Вода»

df.DropColumn("ВОДА");
df.Print();
Рисунок 4. Удаление колонки

Сохранение Daraframe в CSV     

            Для сохранения Dataframe в csv-файл воспользуюсь методом SaveCsv. Рассмотрю один из возможных вариантов записи данных. Первым параметром указываем путь до файла, вторым – нужно ли сохранять индексы строк (если true, то индексы строк будут присутствовать в файле в отдельном столбце Key), третьим – разделитель.

string path_to_save = @"C:\Users\Admin\Desktop\Калорийность_1.csv";
df.SaveCsv(path_to_save, includeRowKeys: true, separator: ';');

В данном материале рассмотрены самые простые методы работы с Dataframe на C#, а именно создание и сохранение Dataframe в файл, выбор строк и колонок, добавление нового столбца и удаление.