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

В настоящее время Python и R являются наиболее популярными языками программирования для исследования данных и управления ими. Это не без уважительной причины, поскольку оба языка просты в использовании и пользуются огромной популярностью у специалистов по анализу данных по всему миру. Фактически, они являются стандартом де-факто, и, вероятно, в ближайшее время он не изменится.

Однако, когда дело доходит до серьезной обработки чисел, необходим более быстрый компилируемый язык. Для этой цели обычно используются такие языки, как C и Java (а теперь даже Swift). C имеет высокий входной барьер и не имеет многих современных функций. Go - отличная альтернатива, простая в освоении и изящная в использовании.

Текущие решения

Для проекта прогнозирования временных рядов на основе машинного обучения я поискал в Интернете достойные пакеты. Go - новый язык, и в некоторых областях трудно найти качественные пакеты. Я нашел самые качественные пакеты:

Я не сомневаюсь в Gonum. Это незаменимый продукт для машинного обучения и статистики.

Мне были нужны DataFrames (похожие на pandas в Python), которые позволяют элегантно сортировать и обрабатывать данные (в духе электронной таблицы Excel). Я обнаружил, что API Gota было очень громоздким в использовании. Я изучил это для создания прототипа, но когда дело дошло до реальной сделки, просто не стоило моего времени постоянно сталкиваться с пакетом только для выполнения простых вещей. На момент написания он не обновлялся в течение года, из-за множества проблем и запросов на вытягивание, которые оставались неподтвержденными.

Итак, я создал DataFrame-Go [Документация]

DataFrame-Go

Задача заключалась в том, чтобы сделать его легким, быстрым и интуитивно понятным. Вам не нужно рыскать по документации, чтобы начать работу - нескольких взглядов должно хватить.

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

Создание фрейма данных

s1 := dataframe.NewSeriesInt64("day", nil, 1, 2, 3, 4, 5, 6, 7, 8)
s2 := dataframe.NewSeriesFloat64("sales", nil, 50.3, 23.4, 56.2, nil, nil, 84.2, 72, 89)
df := dataframe.NewDataFrame(s1, s2)
fmt.Print(df.Table())
OUTPUT:
+-----+-------+---------+
|     |  DAY  |  SALES  |
+-----+-------+---------+
| 0:  |   1   |  50.3   |
| 1:  |   2   |  23.4   |
| 2:  |   3   |  56.2   |
| 3:  |   4   |   NaN   |
| 4:  |   5   |   NaN   |
| 5:  |   6   |  84.2   |
| 6:  |   7   |   72    |
| 7:  |   8   |   89    |
+-----+-------+---------+
| 8X2 | INT64 | FLOAT64 |
+-----+-------+---------+

Вставить и удалить строку

df.Append(nil, 9, 123.6)
df.Append(nil, map[string]interface{}{
 "day":   10,
 "sales": nil,
})
df.Remove(0)
OUTPUT:
+-----+-------+---------+
|     |  DAY  |  SALES  |
+-----+-------+---------+
| 0:  |   2   |  23.4   |
| 1:  |   3   |  56.2   |
| 2:  |   4   |   NaN   |
| 3:  |   5   |   NaN   |
| 4:  |   6   |  84.2   |
| 5:  |   7   |   72    |
| 6:  |   8   |   89    |
| 7:  |   9   |  123.6  |
| 8:  |  10   |   NaN   |
+-----+-------+---------+
| 9X2 | INT64 | FLOAT64 |
+-----+-------+---------+

Обновить строку

df.UpdateRow(0, nil, map[string]interface{}{
 "day":   3,
 "sales": 45,
})

Сортировка

sks := []dataframe.SortKey{
 {Key: "sales", Desc: true},
 {Key: "day", Desc: true},
}
df.Sort(ctx, sks)
OUTPUT:
+-----+-------+---------+
|     |  DAY  |  SALES  |
+-----+-------+---------+
| 0:  |   9   |  123.6  |
| 1:  |   8   |   89    |
| 2:  |   6   |  84.2   |
| 3:  |   7   |   72    |
| 4:  |   3   |  56.2   |
| 5:  |   2   |  23.4   |
| 6:  |  10   |   NaN   |
| 7:  |   5   |   NaN   |
| 8:  |   4   |   NaN   |
+-----+-------+---------+
| 9X2 | INT64 | FLOAT64 |
+-----+-------+---------+

Итерация

iterator := df.ValuesIterator(dataframe.ValuesOptions{0, 1, true})
df.Lock()
for {
 row, vals, _ := iterator()
 if row == nil {
  break
 }
 fmt.Println(*row, vals)
}
df.Unlock()

OUTPUT:
0 map[day:1 0:1 sales:50.3 1:50.3]
1 map[sales:23.4 1:23.4 day:2 0:2]
2 map[day:3 0:3 sales:56.2 1:56.2]
3 map[1:<nil> day:4 0:4 sales:<nil>]
4 map[day:5 0:5 sales:<nil> 1:<nil>]
5 map[sales:84.2 1:84.2 day:6 0:6]
6 map[day:7 0:7 sales:72 1:72]
7 map[day:8 0:8 sales:89 1:89]

Импорт csv

csvStr := `
Country,Date,Age,Amount,Id
"United States",2012-02-01,50,112.1,01234
"United States",2012-02-01,32,321.31,54320
"United Kingdom",2012-02-01,17,18.2,12345
"United States",2012-02-01,32,321.31,54320
"United Kingdom",2012-02-01,NA,18.2,12345
"United States",2012-02-01,32,321.31,54320
"United States",2012-02-01,32,321.31,54320
Spain,2012-02-01,66,555.42,00241
`
df, err := imports.LoadFromCSV(ctx, strings.NewReader(csvStr))
OUTPUT:
+-----+----------------+------------+--------+--------+--------+
|     |    COUNTRY     |    DATE    |  AGE   | AMOUNT |   ID   |
+-----+----------------+------------+--------+--------+--------+
| 0:  | United States  | 2012-02-01 |   50   | 112.1  | 01234  |
| 1:  | United States  | 2012-02-01 |   32   | 321.31 | 54320  |
| 2:  | United Kingdom | 2012-02-01 |   17   |  18.2  | 12345  |
| 3:  | United States  | 2012-02-01 |   32   | 321.31 | 54320  |
| 4:  | United Kingdom | 2012-02-01 |   NA   |  18.2  | 12345  |
| 5:  | United States  | 2012-02-01 |   32   | 321.31 | 54320  |
| 6:  | United States  | 2012-02-01 |   32   | 321.31 | 54320  |
| 7:  |     Spain      | 2012-02-01 |   66   | 555.42 | 00241  |
+-----+----------------+------------+--------+--------+--------+
| 8X5 |     STRING     |   STRING   | STRING | STRING | STRING |
+-----+----------------+------------+--------+--------+--------+

Лицензия

Пакет предоставляется с модифицированной лицензией MIT (mMIT). У него есть все свободы, которые есть у стандартной лицензии MIT, но с дополнительным ограничением, заключающимся в том, что пакет не может использоваться намеренно в военных целях.

DataFrame-Go [Документация]

Другие статьи