Equivalente de Python Pandas en JavaScript


90

Con este ejemplo de CSV:

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

El método estándar que uso Pandas es este:

  1. Analizar CSV

  2. Seleccionar columnas en un marco de datos ( col1y col3)

  3. Procesar la columna (por ejemplo, promediar los valores de col1y col3)

¿Existe una biblioteca de JavaScript que le guste Pandas?


5
Háganos saber con qué terminará yendo. Esta es una pregunta importante para muchos de nosotros.
Ahmed Fasih

Respuestas:


125

Todas las respuestas son buenas. Espero que mi respuesta sea completa (es decir, intenta enumerar todas las opciones). Espero volver y revisar esta respuesta con cualquier criterio para ayudar a tomar una decisión.

Espero que cualquiera que venga aquí esté familiarizado d3. d3es una "navaja suiza" muy útil para manejar datos en Javascript, como pandases útil para Python. Es posible que se d3use con frecuencia como pandas, incluso si nod3 es exactamente un reemplazo de DataFrame / Pandas (es decir d3, no tiene la misma API; d3no tiene Series/ DataFrameque se comporta como en pandas)

La respuesta de Ahmed explica cómo se puede usar d3 para lograr algunas funciones de DataFrame, y algunas de las bibliotecas a continuación se inspiraron en cosas como LearnJsData que usa d3y lodash.

En cuanto a las características centradas en DataFrame, me sentí abrumado con las bibliotecas JS que ayudan. Aquí hay una lista rápida de algunas de las opciones que puede haber encontrado. Todavía no he comprobado ninguno de ellos en detalle (la mayoría los encontré en una combinación de búsqueda de Google + NPM).

Tenga cuidado de utilizar una variedad con la que pueda trabajar; algunos son Node.js, también conocido como Javascript del lado del servidor, algunos son compatibles con el navegador, también conocido como Javascript del lado del cliente. Algunos son mecanografiados.

  • pandas-js
    • De las respuestas de STEEL y Feras
    • "pandas.js es una biblioteca de código abierto (experimental) que imita la biblioteca Python pandas. Se basa en Immutable.js como el equivalente lógico de NumPy. Los principales objetos de datos en pandas.js son, como en Python pandas, la serie y el marco de datos . "
  • dataframe-js
    • "DataFrame-js proporciona una estructura de datos inmutable para javascript y ciencia de datos, el DataFrame, que permite trabajar en filas y columnas con una API inspirada en sql y programación funcional".
  • falsificación de datos
  • jsdataframe
    • "Jsdataframe es una biblioteca de gestión de datos de JavaScript inspirada en la funcionalidad del marco de datos en R y Python Pandas".
  • marco de datos
    • "explorar datos agrupando y reduciendo".

Luego, después de llegar a esta pregunta, verificar otras respuestas aquí y hacer más búsquedas, encontré opciones como:

  • Apache Arrow en JS
    • Gracias a la sugerencia del usuario Back2Basics:
    • "Apache Arrow es una especificación de diseño de memoria en columnas para codificar vectores y contenedores en forma de tabla de datos planos y anidados. Apache Arrow es el estándar emergente para grandes datos en columnas en memoria (Spark, Pandas , Drill, Graphistry, ...)"
  • Observable
    • A primera vista, parece una JSalternativa a los "cuadernos" de IPython / Jupyter
    • La página de Observable promete: "Programación reactiva", una "Comunidad", en una "Plataforma web"
    • Vea la introducción de 5 minutos aquí
  • recline (de la respuesta de Rufus )
    • Esperaba un énfasis en la API de DataFrame, que Pandas intenta preservar de R documentar su sustitución / mejora / correspondencia a cada función R .
    • En cambio, encuentro un énfasis en el ejemplo de recline enfatiza la forma jQuery de introducir datos en el DOMsu (increíble) Multiview (la interfaz de usuario), que no requiere jQuery pero sí requiere un navegador. Más ejemplos
    • ... o un énfasis en su arquitectura MVC-ish ; incluyendo cosas de back-end (es decir, conexiones de base de datos)
    • Probablemente estoy siendo demasiado duro; después de todo, una de las cosas buenas de los pandas es cómo pueden crear visualizaciones fácilmente; fuera de la caja.
  • js-data
    • ¡Realmente más un ORM ! La mayor parte de sus módulos corresponden a diferentes datos de almacenamiento de preguntas ( js-data-mongodb, js-data-redis, js-data-cloud-datastore), la clasificación, filtrado, etc.
    • En el lado positivo, funciona en Node.js como primera prioridad; "Funciona en Node.js y en el navegador".
  • miso (otra sugerencia de Rufus )
  • AlaSQL
    • "AlaSQL" es una base de datos SQL de código abierto para Javascript con un fuerte enfoque en la velocidad de consulta y la flexibilidad de la fuente de datos tanto para datos relacionales como para datos sin esquema. Funciona en su navegador, Node.js y Cordova ".
  • Algunos experimentos mentales:

Espero que esta publicación pueda convertirse en una wiki de la comunidad y evaluar (es decir, comparar las diferentes opciones anteriores) con diferentes criterios como:

  • Criterios de Panda en su comparación R
    • Actuación
    • Funcionalidad / flexibilidad
    • Facilidad de uso
  • Mis propias sugerencias
    • Similitud con las API de Pandas / Dataframe
    • Específicamente sobre sus principales características.
    • Énfasis en la ciencia de datos> Énfasis en la interfaz de usuario
    • Integración demostrada en combinación con otras herramientas como Jupyter (cuadernos interactivos), etc.

Algunas cosas que una biblioteca JS puede que nunca haga (pero ¿podría?)

  • ¿Utiliza un marco subyacente que sea la mejor biblioteca de números / matemáticas de Javascript de su clase? (es decir, un equivalente de NumPy )
  • Use cualquier optimización / compilador que pueda resultar en un código más rápido (es decir, un equivalente al uso de Cython de Pandas )
  • Patrocinado por cualquier consorcio con sabor a ciencia de datos, ala Pandas y NumFocus

1
Gracias por esta maravillosa descripción general. Conozco tanto el uso de marcos de datos pandas como SQL. ¿Cuáles son las ventajas (y desventajas) de usar JS usando marcos de datos en comparación con una base de datos JS SQL?
tardis

@molotow esta es una gran pregunta, pero no tengo mucha experiencia con bases de datos JS SQL (aunque se ven geniales). En general, supongo que los enfoques de tipo marco de datos apoyarían más funciones centradas en la "lucha de datos" / "ciencia de datos", como inferir valores vacíos; haciendo multiplicación de matrices, etc. Mientras que un (JS) SQL está más enfocado en cosas relacionales: consulta, clasificación, filtrado. Por supuesto que habrá superposición; el marco de datos puede UNIRSE, ordenar y filtrar, al igual que SQL incluye algunas funciones estadísticas, etc. ¿Alguien más tiene ideas?
The Red Pea

1
el hecho de que haya tantas opciones es molesto. Más bien, haz que la comunidad se concentre en una sola cosa y que sea buena.
Claudiu Creanga

3
(Autor de Arrow JS aquí) @ClaudiuCreanga Entiendo la frustración. Inicialmente, escribimos ArrowJS en un intento de cerrar la brecha entre los nodos / navegadores y las pilas de big data más tradicionales, y hasta ahora hemos invertido más en excelentes primitivas de IPC / transmisión. Como próximos pasos, nos encantaría comenzar a integrarnos con más bibliotecas JS (tensorflow, d3, etc.), y las relaciones públicas siempre son bienvenidas. Un enfoque alternativo son cosas como el proyecto Perspective de JPMC , que usa ArrowJS para consumir y producir tablas Arrow.
ptaylor

1
¿Existe una funcionalidad para la fusión de marcos de datos en pandas equivalente en javascript?
Phani vikranth

9

He estado trabajando en una biblioteca de lucha de datos para JavaScript llamada data-forge. Está inspirado en LINQ y Pandas.

Se puede instalar así:

npm install --save data-forge

Su ejemplo funcionaría así:

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" ])
        ;

Si sus datos estaban en un archivo CSV, podría cargarlo así:

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

Puede utilizar el selectmétodo para transformar filas.

Puede extraer una columna usando y getSeriesluego usar el selectmétodo para transformar los valores en esa columna.

Obtienes tus datos fuera del marco de datos de esta manera:

var data = dataFrame.toArray();

Para promediar una columna:

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

Hay mucho más que puedes hacer con esto.

Puede encontrar más documentación en npm .


6

Ceaveat ¡ Lo siguiente es aplicable solo a d3 v3, y no al último d4v4!

Soy parcial a d3.js , y aunque no será un reemplazo total para Pandas, si pasa algún tiempo aprendiendo su paradigma, debería poder encargarse de todos sus datos por usted. (Y si termina queriendo mostrar los resultados en el navegador, es ideal para eso).

Ejemplo. Mi archivo CSV data.csv:

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

En el mismo directorio, cree un que index.htmlcontenga lo siguiente:

<!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>

y también un demo.jsarchivo que contiene lo siguiente:

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);
       });

En el directorio, ejecute python -m SimpleHTTPServer 8181y abra http: // localhost: 8181 en su navegador para ver una lista simple de las edades y su promedio.

Este sencillo ejemplo muestra algunas características relevantes de d3:

  • Excelente soporte para la ingesta de datos en línea ( CSV , TSV, JSON, etc.)
  • Inteligencia de gestión de datos incorporada
  • Manipulación DOM basada en datos (quizás lo más difícil de entender): sus datos se transforman en elementos DOM.

2
solo para ayudar a los futuros novatos: las instrucciones anteriores ya no son válidas para d3 v4. creo que la etapa de mapeo se realiza dentro de la devolución de llamada de datos ahora, por ejemplo, github.com/d3/d3-dsv/blob/master/README.md#csvParseRows
swyx

@swyx gracias por el aviso, ¿puedes corregir el ejemplo y publicarlo como respuesta?
Ahmed Fasih

@AhmedFasih Debes corregir tu propia publicación en beneficio de todos. Además, swyx no tiene suficiente reputación para editar su publicación.
Carles Alcolea

@CarlesAlcolea Agregué un gran descargo de responsabilidad en la parte superior, lo siento, no tengo tiempo para ponerme al día con la API actual en este momento 😿
Ahmed Fasih

@AhmedFasih bueno, eso es mejor que antes :) ¡Gracias!
Carles Alcolea

5

Pandas.js en este momento es una biblioteca experimental, pero parece muy prometedor que usa bajo el capó inmutable.js y lógica NumpPy, tanto la serie de objetos de datos como DataFrame están ahí.


3
Parece que la biblioteca no se ha comprometido en más de dos años y parece tener muchos problemas. No diría 'muy prometedor'.
jarthur

4

A continuación se muestra Python numpy y 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)

''

Lo mismo se puede lograr en JavaScript * [ numjs solo funciona con Node.js ] Pero D3.js tiene opciones de conjunto de archivos de datos mucho más avanzadas. Tanto numjs como Pandas-js todavía están en funcionamiento.

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

*/


3

Creo que lo más parecido son bibliotecas como:

Recline, en particular, tiene un objeto Dataset con una estructura algo similar a los marcos de datos de Pandas. A continuación, le permite conectar sus datos con "Vistas", como una cuadrícula de datos, gráficos, mapas, etc. Las vistas suelen ser envolturas finas alrededor de las mejores bibliotecas de visualización existentes, como D3, Flot, SlickGrid, etc.

Aquí hay un ejemplo de reclinarse:

// Cargar algunos datos
var dataset = recline.Model.Dataset ({
  registros: [
    {valor: 1, fecha: '2012-08-07'},
    {valor: 5, b: '2013-09-07'}
  ]
  // Cargar datos CSV en su lugar
  // (Y Recline tiene soporte para muchos más tipos de fuentes de datos)
  // url: 'my-local-csv-file.csv',
  // backend: 'csv'
});

// obtén un elemento de tu HTML para el espectador
var $ el = $ ('# visor de datos');

var allInOneDataViewer = new recline.View.MultiView ({
  modelo: conjunto de datos,
  el: $ el
});
// ¡Tu nuevo visor de datos estará activo!

3

@ neversaint, tu espera ha terminado. da la bienvenida a Danfo.js, que es pandas como la biblioteca Javascript construida en tensorflow.js y admite tensores listos para usar. Esto significa que puede convertir la estructura de datos danfo en tensores. Y puede hacer grupos, fusionar, unir, trazar y otros procesos de datos.


1

Es bastante fácil analizar CSV en javascript porque cada línea ya es esencialmente una matriz de javascript. Si carga su csv en una matriz de cadenas (una por línea), es bastante fácil cargar una matriz de matrices con los 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);
};

Luego getData()devuelve una matriz multidimensional de valores por columna.

He demostrado esto en un jsFiddle para ti.

Por supuesto, no puede hacerlo tan fácilmente si no confía en la entrada, si pudiera haber un script en sus datos que eval podría recoger, etc.


Sé que pusiste una advertencia en tu respuesta, pero realmente no puedo enfatizar lo suficiente lo malo que es este método desde el punto de vista de la seguridad.
xApple

Solo es malo desde el punto de vista de la seguridad si no confía en la entrada. Si, por ejemplo, está haciendo un proyecto escolar en el que ya conoce sus archivos de entrada (porque él o su maestro los ha proporcionado con anticipación en un formato específico), esta es una solución compacta, fácil y legible. No dio ningún contexto con respecto a la fuente de sus entradas, solo solicite una forma de leer el CSV para facilitar el procesamiento.
Steve K

1

Aquí hay un enfoque dinámico asumiendo un encabezado existente en la línea 1. El csv está cargado con 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);         

});

Luego, puede acceder a cada columna de datos similar a un marco de datos R, python o Matlab con df.column_header[row_number].

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.