1

Is there a way to make pandas Dataframes observable?

Lets say I have some Dataframes A, B, C that have the same index and C is calculated by

C = A + B

enter image description here

If I change a cell value in A (e.g. 2 => 4), I would like to automatically update the corresponding cell in C (e.g. 22 => 24).

=> How can I listen to changes in Dataframe A?

Is there some observable Dataframe, triggers or events I could use for that? If that is not possible with pandas Dataframes, is there some other observable table structure I could use?

Or would I need to implement my own spreadsheets?

Additional information:

The index of my tables might consist of multiple columns. There might be multiple value columns, too.

It would be great if I could use that data structure together with RxPy, so that I can create reactive pipes for table calculations.

My calculation pipes/chains might contain hundreds of tables. That's why I don't want to use Excel.

If it is hard to do such things in Python, I am also open for solutions based on JavaScript.

Related stuff

Here is some information I found so far. PyQt tables might be a way to go, because they support change events. However, I am looking for something with "less overhead" for my calculations.

Stefan
  • 7,735
  • 3
  • 43
  • 96

1 Answers1

0

Not a solution for Python, but I found some promising JavaScript libraries:

Based on that libraries I am experimenting with pipes for observable tables here:

https://github.com/stefaneidelloth/rxtable

import * as d3 from 'd3';
import { range, Observable } from 'rxjs';

import DatabaseFactory from './database/databaseFactory';
import KeyContext from './table/keyContext';
import DataContext from './table/dataContext';
import { add } from './operator/operators';

run();

async function run() {
  const databaseFactory = new DatabaseFactory();
  const database = await databaseFactory.create('project');

  const keyContext = new KeyContext(['scenario_id','country_id']);
  const dataContext = new DataContext(['y2020','y2030','y2040']);

  const inputTable = await database.createTable('input', keyContext, dataContext);

  const inputRow = {
    scenario_id: 0,
    country_id: 0,
    y2020: 1,
    y2030: 2,
    y2040: 3,
  };

  let newValue = 4;
  async function buttonClicked() {
    inputRow.y2040 = newValue;
    await inputTable.update(inputRow);
    newValue++;
  }

  d3.select('#root')
    .append('button')
    .text('Click me')
    .on('click', () => buttonClicked());

  // doc for Observable API:
  // https://rxjs.dev/api/index/class/Observable

  // doc for pipe-able operators:
  // https://rxjs.dev/guide/operators
  // https://rxjs.dev/api/operators
  inputTable.pipe(
    add('sum', 66)
  )
  .subscribe({
    initialized(table) {
      console.log(`table: ${table.name}`);
    },
    rowAdded(newRow) {
      console.log(`rowAdded`);
    },
    rowChanged(oldRow, newRow) {
      console.log(`rowChanged`);
    },
    error(error) { console.error(`error: ${error}`); },
    complete() { console.log('done'); },
  });

  await inputTable.push(inputRow);

  await inputTable.push({
    scenario_id: 1,
    country_id: 1,
    y2020: 11,
    y2030: 12,
    y2040: 13,
  });

}

I am still interested in solutions for Python, too. If you know one, please let me know. For those who prefer JavaScript over Python, it might be interesting that someone already started to port pandas to JavaScript: https://stratodem.github.io/pandas.js-docs/#introduction.

Stefan
  • 7,735
  • 3
  • 43
  • 96