[RUBY] Recommandation d'analyse des données à l'aide de MessagePack

MessagePack est un format de sérialisation de données proposé et implémenté par M. Furuhashi de Treasure Data, et est bien connu comme format pour fluentd pour communiquer entre eux. Et je pense que vous l'êtes. Personnellement, je l'utilise souvent pour stocker des données lors de l'analyse de données, et cet article présentera la méthode.

Bien que j'essaie d'écrire l'article aussi précisément que possible, je suis relativement amateur de l'analyse des données, donc j'accueille vos suggestions et commentaires.

Que faire avec MessagePack

Tout ce que vous voulez faire est d'enregistrer les ** données que vous avez obtenues pour analyse au format MessagePack dans un fichier et de lire ces données au moment de l'analyse **.

Normalement, lors de l'analyse de données, etc., il semble que ce soit la voie royale pour les stocker une fois dans une base de données, etc., puis effectuer l'analyse, mais dans les cas suivants, je pense qu'il y a un mérite à enregistrer et à lire au format MessagePack. ..

Si vous êtes satisfait de MessagePack

Lorsque le schéma gère des données peu claires

Par exemple, si la sortie de données d'un certain système est JSON au format dictionnaire, les clés incluses dans chaque enregistrement sont différentes, le format de ce qui est entré en tant que valeur est différent et on ne sait pas si le format du dictionnaire ou le format du tableau est fourni. Ou quelque chose comme ça. De plus, même si la clé ou la valeur change, il est bon qu'un tel schéma ou spécification soit correctement défini, mais il y a des cas où il n'y a pas d'autre choix que d'estimer à partir des données réelles sans même la spécification.

Dans un tel cas, MessagePack peut convertir la structure hiérarchique telle que les dictionnaires et les tableaux presque telle quelle et l'utiliser, il est donc facile de l'insérer dans le fichier sans penser à quoi que ce soit pour le moment. Lors de la récupération de données pour l'analyse des données, les E / S de données deviennent souvent un goulot d'étranglement, de sorte que leur enregistrement localement dans un format de fichier facilite les essais et erreurs par la suite.

Lorsque vous souhaitez enregistrer des données temporairement ou lorsque vous souhaitez enregistrer et charger des données à plusieurs reprises

Il y a beaucoup de choses que l'on peut appeler analyse de données, mais il est souvent nécessaire de réaliser une «analyse exploratoire des données» pour saisir le tableau d'ensemble et formuler une hypothèse en pétrissant les données au stade où une hypothèse suffisante ne peut être établie. Dans un tel cas, vous pouvez convertir les données dans un format facile à traiter, extraire uniquement les données nécessaires et les enregistrer, etc. Dans ce cas, je pense qu'il peut y avoir des essais et des erreurs concernant le format des données, comme "Je veux ajouter cet attribut pour un moment" ou "Il semble préférable de l'enregistrer sous forme de dictionnaire plutôt que de liste".

Lors du traitement tout en modifiant de manière flexible le format des données de cette manière, lorsque le côté code est modifié en définissant à nouveau le schéma dans un endroit autre que le code qui traite les données (par exemple, créer une table avec SQL), etc. Des incohérences peuvent survenir dans chaque cas, ce qui peut être très gênant. D'autre part, si vous souhaitez enregistrer des données au format MessagePack, bien sûr, vous devez faire correspondre le format de données à la fois pour l'écriture et la lecture, mais le travail est minime.

(Cependant, si vous ne laissez pas de commentaires dans une certaine mesure, vous risquez de ne pas comprendre du tout le sens même si vous relisez le code vous-même quelques mois plus tard ...)

Lorsque vous devez enregistrer et charger des données à grande vitesse (mais en texte intégral)

DB en tant que middleware stocke non seulement simplement les données, mais fournit également diverses fonctions telles que la définition des clés et la garantie de la fiabilité, ce qui prend plus de temps que la simple écriture sur disque. .. Cela peut être résolu par des techniques telles que la distribution de charge, mais si vous voulez simplement "sauvegarder un peu de données", vous pouvez le convertir au format MessagePack et l'écrire directement sous forme de fichier. Cependant, les performances d'écriture et de lecture des fichiers sont appliquées presque telles quelles.

Cependant, la fiabilité est la même que l'écriture dans un fichier et on suppose que toutes les données sont lues lors de la lecture.

Si vous n'êtes pas satisfait de MessagePack

D'un autre côté, bien sûr, il y a des cas où il ne convient pas d'enregistrer au format MessagePack et d'analyser les données.

  1. Lors de l'utilisation de données avec un schéma clair ou des données initialement organisées par DB, etc. ――Vous devez utiliser la fonction fournie par DB tranquillement
  2. Pour des analyses telles que la recherche et l'agrégation, où les avantages de la création de clés et d'index sont grands.
  1. Lorsque plusieurs personnes gèrent les mêmes données ――Cette fois, nous supposons la lecture et l'écriture d'un fichier, donc le verrouillage, etc. n'est pas pris en compte
  2. Assurer la confidentialité, l'intégrité et la disponibilité des données

Proposition alternative

Les technologies suivantes peuvent être considérées comme des alternatives. Veuillez sélectionner en fonction de la situation.

CSV

Il est préférable d'utiliser CSV (ou TSV) si les données sont dans un format de colonne de longueur presque fixe et non structurées de manière hiérarchique. Cependant, il est plus facile d'utiliser MessagePack lorsque des éléments de longueur variable et des structures hiérarchiques sont inclus.

MongoDB

Vous pouvez insérer sans définir de schéma dans une base de données orientée document, de sorte que vous pouvez faire de même à partir du point de sauvegarde des données pour le moment. Cependant, les performances de l'insertion semblent être 3 500 insert / s de trop, et lors de l'écriture avec MessagePack, il n'écrit que directement sur le disque, donc L'enregistrement avec MessagePack, qui conserve les performances des E / S de disque, est extrêmement rapide. Cependant, si vous souhaitez créer des clés plus tard, MongoDB sera plus adapté.

JSON, BSON

Il est désavantageux par rapport à MessagePack en termes de vitesse de traitement et de taille des données (référence). De plus, JSON est un module qui lit par étapes comme ijson lorsque vous souhaitez placer plusieurs objets dans un segment de données (par exemple, un fichier). Si vous ne l'utilisez pas, vous devez tout analyser en même temps, donc si le nombre de données est important, le traitement sera difficile sur une machine médiocre. D'un autre côté, si vous l'écrivez comme ijson, le code sera compliqué, donc je pense personnellement qu'il est plus facile de stocker des données en continu dans un segment de données et de les récupérer docilement.

Protocol Buffers

Protocol Buffers est réputé comme l'une des technologies de sérialisation, mais il faut du temps pour traiter des données dont le schéma n'est pas clair car il est nécessaire de définir le schéma côté code de traitement. Lorsqu'elle est considérée comme une sérialisation de données comme une interface entre les logiciels, elle est pratique car elle régule le schéma, mais elle devient difficile à gérer dans les cas où vous ne savez pas quel type de données de schéma viendra.

Exemple de code

Il y a beaucoup d'explications sur la page officielle, donc je n'ai pas besoin de beaucoup parler, mais je présenterai l'exemple de code en se concentrant uniquement sur l'écriture et la lecture du fichier. Le code peut également être trouvé sur github.

Dans tous les cas, les données suivantes doivent être écrites / lues dans le fichier «data.msg».

{
  "name": "Alice", 
  "age": 27,
  "hist": [5, 3, 1]
}
{
  "name": "Bob", 
  "age": 33,
  "hist": [4, 5]
}

Python

Le package msgpack-python est requis.

Installation

$ pip install msgpack-python

Écrire un exemple de code

# coding: UTF-8

import msgpack

obj1 = {
    "name": "Alice",
    "age": 27,
    "hist": [5, 3, 1]
}
obj2 = {
    "name": "Bob",
    "age": 33,
    "hist": [4, 5]
}

with open('data.msg', 'w') as fd:
    fd.write(msgpack.packb(obj1))
    fd.write(msgpack.packb(obj2))

Lire un exemple de code

# coding: UTF-8

import msgpack

for msg in msgpack.Unpacker(open('data.msg', 'rb')):
    print msg

Ruby

Le package msgpack est requis.

$ gem install msgpack

Écrire un exemple de code

# -*- coding: utf-8 -*-

require "msgpack"

obj1 = {
    "name": "Alice",
    "age": 27,
    "hist": [5, 3, 1]
}
obj2 = {
    "name": "Bob",
    "age": 33,
    "hist": [4, 5]
}

File.open("data.msg", "w") do |file|
  file.write(obj1.to_msgpack)
  file.write(obj2.to_msgpack)
end

Lire un exemple de code

# -*- coding: utf-8 -*-

require "msgpack"

File.open("data.msg") do |file|
  MessagePack::Unpacker.new(file).each do |obj|
    puts obj
  end
end

Node

Il existe quelques bibliothèques MessagePack majeures, mais cette fois j'utiliserai msgpack-lite pour le code.

$ npm install msgpack-lite

Écrire un exemple de code

const fs = require('fs');
const msgpack = require('msgpack-lite');

const obj1 = {
  name: "Alice",
  age: 27,
  hist: [5, 3, 1]
};
const obj2 = {
  name: "Bob",
  age: 33,
  hist: [4, 5]
};

fs.open('data.msg', 'w', (err, fd) => {
  fs.writeSync(fd, msgpack.encode(obj1));
  fs.writeSync(fd, msgpack.encode(obj2));
});

Lire un exemple de code

const fs = require('fs');
const msgpack = require('msgpack-lite');

var rs = fs.createReadStream('data.msg');
var ds = msgpack.createDecodeStream();

rs.pipe(ds).on('data', (msg) => {
  console.log(msg);
});

C++

La bibliothèque msgpackc est requise. Pour macOS, vous pouvez l'installer avec brew.

$ brew install msgpack

Écrire un exemple de code

#include <msgpack.hpp>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  int fd = open("data.msg", O_WRONLY | O_CREAT, 0600);

  msgpack::sbuffer buf1, buf2;;
  msgpack::packer<msgpack::sbuffer> pk1(&buf1), pk2(&buf2);

  pk1.pack_map(3);
  pk1.pack("name"); pk1.pack("Alice");
  pk1.pack("age");  pk1.pack(27);
  pk1.pack("hist");
  pk1.pack_array(3);
  pk1.pack(5); pk1.pack(3); pk1.pack(1);

  write(fd, buf1.data(), buf1.size());


  pk2.pack_map(3);
  pk2.pack("name"); pk2.pack("Bob");
  pk2.pack("age");  pk2.pack(33);
  pk2.pack("hist");
  pk2.pack_array(2);
  pk2.pack(4); pk2.pack(5);

  write(fd, buf2.data(), buf2.size());

  close(fd);
  return 0;
}

Lire un exemple de code

#include <msgpack.hpp>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char *argv[]) {
  static const size_t BUFSIZE = 4; //Osez réduire la taille du tampon
  int rc;
  char buf[BUFSIZE];

  int fd = open("data.msg", O_RDONLY);

  msgpack::unpacker unpkr;
  while (0 < (rc = read(fd, buf, sizeof(buf)))) {
    unpkr.reserve_buffer(rc);
    memcpy(unpkr.buffer(), buf, rc);
    unpkr.buffer_consumed(rc);

    msgpack::object_handle result;
    while (unpkr.next(result)) {
      const msgpack::object &obj = result.get();

      if (obj.type == msgpack::type::MAP) {
        printf("{\n");
        msgpack::object_kv* p(obj.via.map.ptr);

        for(msgpack::object_kv* const pend(obj.via.map.ptr + obj.via.map.size);
            p < pend; ++p) {

          std::string key;
          p->key.convert(key);

          if (key == "name") {
            std::string value;
            p->val.convert(value);
            printf("  %s: %s,\n", key.c_str(), value.c_str());
          }

          if (key == "age") {
            int value;
            p->val.convert(value);
            printf("  %s: %d,\n", key.c_str(), value);
          }

          if (key == "hist") {
            msgpack::object arr = p->val;
            printf ("  %s, [", key.c_str());
            for (int i = 0; i < arr.via.array.size; i++) {
              int value;
              arr.via.array.ptr[i].convert(value);

              printf("%d, ", value);
            }
            printf ("],\n");
          }
        }

        printf("}\n");
      }

      result.zone().reset();
    }
  }

  return 0;
}

Au fait, si vous lancez le format msgpack :: object dans ʻostream (std :: cout` etc.), le format sera formaté et affiché sans permission, mais il est difficile comme décrit ci-dessus de récupérer la valeur par programme. La procédure est décrite comme un exemple.

Recommended Posts

Recommandation d'analyse des données à l'aide de MessagePack
Analyse des données à l'aide de xarray
Analyse de données à l'aide de pandas python
[Python] [Word] [python-docx] Analyse simple des données de diff en utilisant python
Analyse des données de mesure (2) -Hydrobacter et raccord, recommandation lmfit-
Analyse des séries chronologiques 3 Prétraitement des données des séries chronologiques
Tutoriel de recommandation utilisant l'analyse d'association (concept)
Traitement des données 2 Analyse de divers formats de données
Construction d'un système de recommandation utilisant le bouche-à-oreille doc2vec
Tutoriel de recommandation utilisant l'analyse d'association (implémentation python)
Création d'une application d'analyse de données à l'aide de Streamlit
Recommandation d'Altair! Visualisation des données avec Python
Connaissance de l'utilisation de l'API de données Aurora Severless
Analyse de données python
Analyser émotionnellement les données de bouche-à-oreille d'entreprise des réunions de changement de carrière à l'aide de l'apprentissage en profondeur
Analyse des données Titanic 1
J'ai essayé d'effectuer une analyse de cluster de clients à l'aide des données d'achat
Analyse de la variation temporelle des trous noirs en utilisant Python
[Pandas] Principes de base du traitement des données de date à l'aide de dt
Étude introductive sur Python-Sortie des données de vente à l'aide de tapple-
Environnement enregistré pour l'analyse des données avec Python
Vérifiez l'état des données à l'aide de pandas_profiling
Gratter les données gagnantes de Numbers à l'aide de Docker
Une introduction à l'analyse de données à l'aide de Python - Pour augmenter le nombre de vues vidéo -
Analyse de données avec python 2
Explication du concept d'analyse de régression à l'aide de python Partie 2
Résumé des méthodes d'analyse de données statistiques utilisant Python qui peuvent être utilisées en entreprise
Analyse des données financières par pandas et leur visualisation (1)
Analyse de Big Data à l'aide du framework de contrôle de flux de données Luigi
Nettoyage des données 2 Nettoyage des données à l'aide de DataFrame
Nettoyage des données à l'aide de Python
Analyse des données de mesure ①-Mémorandum de montage scipy-
Histoire de l'analyse d'image du fichier PDF et de l'extraction de données
Explication du concept d'analyse de régression à l'aide de Python Partie 1
[Didacticiel d'analyse Python dans la base de données avec SQL Server 2017] Étape 4: Extraction de fonctionnalités de données à l'aide de T-SQL
J'ai essayé d'utiliser l'API de Sakenowa Data Project
Pré-traitement des données préfectorales
Analyse orthologue à l'aide d'OrthoFinder
Bases de l'analyse de régression
Exemple d'utilisation de lambda
Sélection des données de mesure
Analyse de données avec Python
[Livre technique] Introduction à l'analyse de données avec Python -1 Chapitre Introduction-
Analyse de la vie de la technologie avec les données d'articles Qiita ~ Analyse du temps de survie à l'aide du journal de contenu ~
Créez instantanément un diagramme de données 2D à l'aide de matplotlib de python
Recommandation de Jupyter Notebook, un environnement de codage pour les data scientists
Faisons l'analyse des données de naufrage du Titanic comme ça
Première étape de l'analyse des données (nombre de données, affichage du tableau, valeurs manquantes)
Analyse des contraintes du tore sous pression interne à l'aide d'un programme d'analyse des contraintes à symétrie axiale
Analyse des données basée sur les résultats des élections du gouverneur de Tokyo (2020)
[Introduction] Analyse de données satellitaires artificielles à l'aide de Python (environnement Google Colab)
J'ai essayé d'analyser les données scRNA-seq en utilisant l'analyse des données topologiques (TDA)
Mon conteneur d'analyse de données python
Xarray de bibliothèque d'analyse de données multidimensionnelle
Implémentation de TF-IDF à l'aide de gensim
Python pour l'analyse des données Chapitre 4
Expérience de réglage des données Tensorflow
Sélectionnez des fonctionnalités avec des données textuelles