Python Pandas equivalente em JavaScript

96

Com este exemplo CSV:

   Source,col1,col2,col3
   foo,1,2,3
   bar,3,4,5

O método padrão que uso o Pandas é este:

  1. Analisar CSV

  2. Selecione colunas em um quadro de dados ( col1e col3)

  3. Processe a coluna (por exemplo, média dos valores de col1e col3)

Existe uma biblioteca JavaScript que faz isso como o Pandas?

neversaint
fonte
6
Deixe-nos saber o que você vai fazer. Esta é uma questão importante para muitos de nós.
Ahmed Fasih

Respostas:

133

Todas as respostas são boas. Esperando que minha resposta seja abrangente (ou seja, tenta listar todas as opções). Espero retornar e revisar esta resposta com quaisquer critérios para ajudar a fazer uma escolha.

Espero que alguém que venha aqui conheça d3. d3é um "canivete suíço" muito útil para lidar com dados em Javascript, como pandasé útil para Python. Você pode ver d3usado com frequência como pandas, mesmo que nãod3 seja exatamente uma substituição do DataFrame / Pandas (ou seja d3, não tem a mesma API; d3não tem Series/ DataFrameque se comporta como em pandas)

A resposta de Ahmed explica como d3 pode ser usado para obter algumas funcionalidades do DataFrame, e algumas das bibliotecas abaixo foram inspiradas em coisas como LearnJsData que usa d3e lodash.

Quanto aos recursos focados em DataFrame, fiquei sobrecarregado com bibliotecas JS que ajudam. Aqui está uma lista rápida de algumas das opções que você pode ter encontrado. Eu não verifiquei nenhum deles em detalhes ainda (a maioria eu encontrei na combinação de pesquisa Google + NPM).

Tenha cuidado ao usar uma variedade com a qual possa trabalhar; alguns são Node.js, também conhecido como Javascript do lado do servidor, outros são compatíveis com o navegador, também conhecido como Javascript do lado do cliente. Alguns são datilografados.

  • pandas-js
    • Das respostas de STEEL e Feras
    • "pandas.js é uma biblioteca de código aberto (experimental) que imita a biblioteca Python pandas. Ela se baseia em Immutable.js como o equivalente lógico do NumPy. Os principais objetos de dados em pandas.js são, como em Python pandas, a série e o DataFrame . "
  • dataframe-js
    • "DataFrame-js fornece uma estrutura de dados imutável para javascript e datascience, o DataFrame, que permite trabalhar em linhas e colunas com um sql e API inspirada em programação funcional."
  • forja de dados
  • jsdataframe
    • "Jsdataframe é uma biblioteca de manipulação de dados JavaScript inspirada na funcionalidade de quadro de dados em R e Python Pandas."
  • quadro de dados
    • "explorar dados agrupando e reduzindo."

Então, depois de chegar a esta pergunta, verificando outras respostas aqui e fazendo mais pesquisas, encontrei opções como:

  • Apache Arrow em JS
    • Agradecimentos à sugestão do usuário Back2Basics:
    • "Apache Arrow é uma especificação de layout de memória colunar para codificação de vetores e contêineres semelhantes a tabelas de dados planos e aninhados. Apache Arrow é o padrão emergente para grandes dados colunares na memória (Spark, Pandas , Drill, Graphistry, ...)"
  • Observável
    • À primeira vista, parece uma JSalternativa aos "notebooks" IPython / Jupyter
    • A página da Observable promete: "Programação reativa", uma "Comunidade", em uma "Plataforma Web"
    • Veja a introdução de 5 minutos aqui
  • reclinar (da resposta de Rufus )
    • Eu esperava uma ênfase na API do DataFrame, que o próprio Pandas tenta preservar de R documentar a sua substituição / melhoria / correspondência a todas as funções R .
    • Em vez disso, acho que o exemplo de reclinar ênfase enfatiza a maneira jQuery de obter dados no DOMsua (incrível) Multiview (a IU), que não requer jQuery, mas requer um navegador! Mais exemplos
    • ... ou uma ênfase em sua arquitetura MVC ; incluindo coisas de back-end (ou seja, conexões de banco de dados)
    • Provavelmente estou sendo muito duro; afinal, uma das coisas boas sobre os pandas é como eles podem criar visualizações facilmente; sai da caixa.
  • js-data
    • Realmente mais de um ORM ! A maioria dos seus módulos correspondem a diferentes dados de armazenamento perguntas ( js-data-mongodb, js-data-redis, js-data-cloud-datastore), triagem, filtragem, etc.
    • No lado positivo, funciona no Node.js como primeira prioridade; "Funciona em Node.js e no navegador."
  • miso (outra sugestão de Rufus )
  • AlaSQL
    • "AlaSQL" é um banco de dados SQL de código aberto para Javascript com um forte foco na velocidade de consulta e flexibilidade da fonte de dados para dados relacionais e dados sem esquema. Funciona no seu navegador, Node.js e Cordova. "
  • Alguns experimentos mentais:

Espero que esta postagem se torne um wiki da comunidade e avalie (ou seja, compare as diferentes opções acima) em relação a diferentes critérios como:

  • Critérios da Panda em sua comparação R
    • atuação
    • Funcionalidade / flexibilidade
    • Fácil de usar
  • Minhas próprias sugestões
    • Semelhança com APIs de Pandas / Dataframe
    • Hits especificamente em seus principais recursos
    • Ênfase em ciência de dados> Ênfase na interface do usuário
    • Integração demonstrada em combinação com outras ferramentas como Jupyter (notebooks interativos), etc

Algumas coisas que uma biblioteca JS pode nunca fazer (mas poderia?)

  • Use uma estrutura subjacente que seja a melhor biblioteca de números / matemática Javascript da classe? (ou seja, um equivalente a um NumPy )
  • Use qualquer otimização / compilador que possa resultar em código mais rápido (ou seja, um equivalente ao uso de Cython pelo Pandas )
  • Patrocinado por quaisquer consórcios de ciência de dados, ala Pandas e NumFocus
The Red Pea
fonte
1
Obrigado por esta visão geral maravilhosa. Eu conheço o uso de dataframes do pandas e SQL. Quais são as vantagens (e desvantagens) de usar JS usando dataframes versus um banco de dados JS SQL?
tardis
@molotow esta é uma ótima pergunta, mas eu não tenho muita experiência com bancos de dados JS SQL (embora eles tenham uma aparência legal). Em geral eu acho que as abordagens do tipo trama de dados iria apoiar mais "dados disputas" / "data-ciência" focado funções, como inferir valores vazios; fazer multiplicação de matrizes, etc. Considerando que um (JS) SQL é mais focado em coisas relacionais: consultar, classificar, filtrar. Claro que haverá sobreposição; dataframe pode JOIN, classificar e filtrar, assim como o SQL inclui algumas funções estatísticas e etc. Alguém mais tem ideias?
The Red Pea
1
o fato de haver tantas opções é irritante. Em vez disso, faça com que a comunidade se concentre em apenas uma coisa e torne-a boa.
Claudiu Creanga
3
(Arrow autor de JS aqui) @ClaudiuCreanga Eu entendo a frustração. Inicialmente, escrevemos ArrowJS em uma tentativa de diminuir a divisão entre nós / navegadores e as pilhas de big data mais tradicionais, e investimos mais pesadamente em primitivos IPC / streaming excelentes até agora. Como próximas etapas, adoraríamos começar a integração com mais bibliotecas JS (tensorflow, d3, etc.), e PRs são sempre bem-vindos. Uma abordagem alternativa é o projeto Perspectiva do JPMC , que usa o ArrowJS para consumir e produzir tabelas Arrow.
ptaylor de
1
existe uma funcionalidade para a fusão de dataframe em pandas equivalente em javascript?
Phani vikranth
9

Tenho trabalhado em uma biblioteca de organização de dados para JavaScript chamada data-forge. É inspirado em LINQ e Pandas.

Ele pode ser instalado assim:

npm install --save data-forge

Seu exemplo funcionaria assim:

var csvData = "Source,col1,col2,col3\n" +
    "foo,1,2,3\n" +
    "bar,3,4,5\n";

var dataForge = require('data-forge');
var dataFrame = 
    dataForge.fromCSV(csvData)
        .parseInts([ "col1", "col2", "col3" ])
        ;

Se seus dados estiverem em um arquivo CSV, você poderá carregá-lo assim:

var dataFrame = dataForge.readFileSync(fileName)
    .parseCSV()
    .parseInts([ "col1", "col2", "col3" ])
    ;

Você pode usar o selectmétodo para transformar linhas.

Você pode extrair uma coluna usando getSerieso selectmétodo para transformar os valores dessa coluna.

Você obtém seus dados de volta do data-frame assim:

var data = dataFrame.toArray();

Para calcular a média de uma coluna:

 var avg = dataFrame.getSeries("col1").average();

Você pode fazer muito mais com isso.

Você pode encontrar mais documentação sobre npm .

Ashley Davis
fonte
8

Ceaveat O seguinte é aplicável apenas ao d3 v3, e não ao d4v4 mais recente!

Eu tenho uma preferência pelo d3.js e, embora não seja uma substituição total do Pandas, se você passar algum tempo aprendendo seu paradigma, ele deve ser capaz de cuidar de todas as suas disputas de dados para você. (E se você quiser exibir os resultados no navegador, ele é ideal para isso.)

Exemplo. Meu arquivo CSV data.csv:

name,age,color
Mickey,65,black
Donald,58,white
Pluto,64,orange

No mesmo diretório, crie um index.htmlcontendo o seguinte:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
    <title>My D3 demo</title>

    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
  </head>
  <body>

      <script charset="utf-8" src="demo.js"></script>
  </body>
</html>

e também um demo.jsarquivo contendo o seguinte:

d3.csv('/data.csv',

       // How to format each row. Since the CSV file has a header, `row` will be
       // an object with keys derived from the header.
       function(row) {
         return {name : row.name, age : +row.age, color : row.color};
       },

       // Callback to run once all data's loaded and ready.
       function(data) {
         // Log the data to the JavaScript console
         console.log(data);

         // Compute some interesting results
         var averageAge = data.reduce(function(prev, curr) {
           return prev + curr.age;
         }, 0) / data.length;

         // Also, display it
         var ulSelection = d3.select('body').append('ul');
         var valuesSelection =
             ulSelection.selectAll('li').data(data).enter().append('li').text(
                 function(d) { return d.age; });
         var totalSelection =
             ulSelection.append('li').text('Average: ' + averageAge);
       });

No diretório, execute python -m SimpleHTTPServer 8181e abra http: // localhost: 8181 em seu navegador para ver uma lista simples das idades e sua média.

Este exemplo simples mostra alguns recursos relevantes do d3:

  • Excelente suporte para ingestão de dados online ( CSV , TSV, JSON, etc.)
  • Inteligência de luta de dados incorporada
  • Manipulação de DOM orientada por dados (talvez a coisa mais difícil de entender): seus dados são transformados em elementos DOM.
Ahmed Fasih
fonte
2
apenas para ajudar futuros novatos - as instruções acima não são mais válidas para d3 v4. acho que o estágio de mapeamento é feito dentro do retorno de chamada de dados agora, por exemplo, github.com/d3/d3-dsv/blob/master/README.md#csvParseRows
swyx
@swyx obrigado pelo aviso, você pode corrigir o exemplo e postar como resposta?
Ahmed Fasih
@AhmedFasih Você deve corrigir sua própria postagem para o benefício de todos. Além disso, swyx não tem reputação suficiente para editar sua postagem.
Carles Alcolea
@CarlesAlcolea Eu adicionei um grande aviso no topo, desculpe, eu não tenho tempo para acelerar a API atual agora 😿
Ahmed Fasih
@AhmedFasih bem, isso é melhor do que antes :) Obrigado!
Carles Alcolea de
5

Abaixo está Python entorpecido e pandas

`` `

import numpy as np
import pandas as pd

data_frame = pd.DataFrame(np.random.randn(5, 4), ['A', 'B', 'C', 'D', 'E'], [1, 2, 3, 4])

data_frame[5] = np.random.randint(1, 50, 5)

print(data_frame.loc[['C', 'D'], [2, 3]])

# axis 1 = Y | 0 = X
data_frame.drop(5, axis=1, inplace=True)

print(data_frame)

`` `

O mesmo pode ser alcançado em JavaScript * [ numjs funciona apenas com Node.js ] Mas D3.js tem opções muito avançadas de conjunto de arquivos de dados. Tanto numjs quanto Pandas-js ainda em obras ..

import np from 'numjs';
import { DataFrame } from 'pandas-js';

const df = new DataFrame(np.random.randn(5, 4), ['A', 'B', 'C', 'D', 'E'], [1, 2, 3, 4])

// df
/*

          1         2         3         4
A  0.023126  1.078130 -0.521409 -1.480726
B  0.920194 -0.201019  0.028180  0.558041
C -0.650564 -0.505693 -0.533010  0.441858
D -0.973549  0.095626 -1.302843  1.109872
E -0.989123 -1.382969 -1.682573 -0.637132

*/

AÇO
fonte
5

No momento, o Pandas.js é uma biblioteca experimental, mas parece muito promissor, pois usa sob o capô immutable.js e lógica NumpPy, ambas séries de objetos de dados e DataFrame estão lá.

Feras
fonte
3
Parece que a biblioteca não tem um commit há mais de dois anos e parece ter muitos problemas. Eu não diria 'muito promissor'.
jarthur
4

@neversaint sua espera acabou. diga bem-vindo ao Danfo.js que é um pandas como a biblioteca Javascript construída em tensorflow.js e oferece suporte a tensores prontos para uso. Isso significa que você pode converter a estrutura de dados danfo em tensores. E você pode fazer agrupamento, fusão, união, plotagem e outro processamento de dados.

Vignesh Prajapati
fonte
3

Acho que o mais próximo são bibliotecas como:

Recline, em particular, tem um objeto Dataset com uma estrutura um pouco semelhante aos data frames do Pandas. Em seguida, ele permite que você conecte seus dados com "Visualizações", como uma grade de dados, gráficos, mapas, etc. As visualizações são geralmente pacotes finos em torno das melhores bibliotecas de visualização existentes, como D3, Flot, SlickGrid etc.

Aqui está um exemplo para Reclinar:

// Carrega alguns dados
var dataset = recline.Model.Dataset ({
  registros: [
    {valor: 1, data: '07/08/2012'},
    {valor: 5, b: '07/09/2013'}
  ]
  // Carrega dados CSV em seu lugar
  // (E Recline tem suporte para muitos outros tipos de fonte de dados)
  // url: 'my-local-csv-file.csv',
  // backend: 'csv'
});

// obtém um elemento do seu HTML para o visualizador
var $ el = $ ('# data-viewer');

var allInOneDataViewer = new recline.View.MultiView ({
  modelo: conjunto de dados,
  el: $ el
});
// Seu novo Visualizador de Dados estará ativo!
Rufus Pollock
fonte
1

É muito fácil analisar CSV em javascript porque cada linha já é essencialmente um array de javascript. Se você carregar seu csv em um array de strings (um por linha), é muito fácil carregar um array de arrays com os valores:

var pivot = function(data){
    var result = [];
    for (var i = 0; i < data.length; i++){
        for (var j=0; j < data[i].length; j++){
            if (i === 0){
                result[j] = [];
            }
            result[j][i] = data[i][j];
        }
    }
    return result;
};

var getData = function() {
    var csvString = $(".myText").val();
    var csvLines = csvString.split(/\n?$/m);

    var dataTable = [];

    for (var i = 0; i < csvLines.length; i++){
        var values;
        eval("values = [" + csvLines[i] + "]");
        dataTable[i] = values;
    }

    return pivot(dataTable);
};

Em seguida, getData()retorna uma matriz multidimensional de valores por coluna.

Eu demonstrei isso em um jsFiddle para você.

Claro, você não pode fazer isso tão facilmente se não confiar na entrada - se pudesse haver um script em seus dados que a avaliação poderia pegar, etc.

Steve K
fonte
Eu sei que você colocou um aviso em sua resposta, mas eu realmente não posso enfatizar o suficiente o quão ruim esse método é do ponto de vista da segurança.
x Apple de
Só é ruim do ponto de vista da segurança se ele não confiar nas informações. Se, por exemplo, ele está fazendo um projeto escolar em que já conhece seus arquivos de entrada (porque ele ou seu professor os forneceu antecipadamente em um formato específico), esta é uma solução compacta, fácil e legível. Ele não deu nenhum contexto sobre a origem de suas entradas, apenas pediu uma maneira de ler o CSV para facilitar o processamento.
Steve K
1

Aqui está uma abordagem dinâmica assumindo um cabeçalho existente na linha 1. O csv é carregado com d3.js.

function csvToColumnArrays(csv) {

    var mainObj = {},
    header = Object.keys(csv[0]);

    for (var i = 0; i < header.length; i++) {

        mainObj[header[i]] = [];
    };

    csv.map(function(d) {

        for (key in mainObj) {
            mainObj[key].push(d[key])
        }

    });        

    return mainObj;

}


d3.csv(path, function(csv) {

    var df = csvToColumnArrays(csv);         

});

Então você pode acessar cada coluna dos dados de forma semelhante a um dataframe R, python ou Matlab com df.column_header[row_number].

Manuel
fonte