fumitoh / modelx

Use Python like a spreadsheet!
https://modelx.io
GNU Lesser General Public License v3.0
90 stars 20 forks source link

Writing models with such objects as DataFrames as refs or as Cells values #15

Open alebaran opened 4 years ago

alebaran commented 4 years ago

I need to create a cell with no arguments and some data inside. Is there a way to do it so that "write_model" will capture it?

fumitoh commented 4 years ago

Are you referring to no-arg cells with simple values like the attached? Currently no way to write cells with values that are instances of user-defined classes as I wrote here: https://github.com/fumitoh/modelx/issues/8#issuecomment-536200063

NoArgCells.xlsx

alebaran commented 4 years ago

I'm looking for no-arg cells with pandas (DataFrame/Series) content. The same as new_cells_from_pandas, but without argument

fumitoh commented 4 years ago

You can assign your pandas object to a ref, and refer to the ref from your cells. That's the only way available now. I'm working on dependency tracking on refs as well. Once it's available then you don't have much incentive to store constants in cells.

alebaran commented 4 years ago

I actually like the concept of storing all the data in cells regardless if these are cells with or without args. Why would to prohibit storing data in cells without args?

fumitoh commented 4 years ago

I'm not prohibiting storing data in cells without args. The bottom line is, currently it not possible to store values of arbitrary cells with write_model, so need some work to enhance write_model. I'll put that on the requested feature stack.

alebaran commented 4 years ago

Thanks. At the moment I'm storing data in the cells without args using low level calls: space.new_cells(name= name, formula=mx.core.util.get_param_func(cells_params))

fumitoh commented 4 years ago

Not sure I'm following you. You want to do something like below correct? How does the mx.core.util.get_param_func help?

import pandas as pd
import modelx as mx

m, s = mx.new_model(), mx.new_space()

s.new_cells(name="NoArg") # creating a non-arg cells

df = pd.DataFrame({"A": [1,2,3], "B":[4,5,6]})

s.NoArg = df # assign df to NoArg

s.NoArg() # returns df

mx.write_model(m, "NoArg")
m2 = mx.read_model("NoArg")

m2.Space1.NoArg # non-arg cells is restored

m2.Space1.NoArg() # You want this to return df 
alebaran commented 4 years ago

I'm not using new_cells_from_pandas function yet. Instead I've built my own function using mx.core.util.get_param_func, which does something very close to new_cells_from_pandas. I would like to migrate to using new_cells_from_pandas and checking if it covers all my needs. That's where the question above comes from. The approach you are describing above is a good workaround.

fumitoh commented 4 years ago

(correction) The comment below was for #13 , posted here by mistake.

v0.0.25 is released and the stack tracing feature is introduced. See https://modelx.readthedocs.io/en/latest/releases/relnotes_v0_0_25.html

alebaran commented 4 years ago

The new version is awesome!!! It allows me to fully track the number of calls to the function and the time it takes to evaluate each call. Thank you very much!

alebaran commented 4 years ago

Not sure I'm following you. You want to do something like below correct? How does the mx.core.util.get_param_func help?

import pandas as pd
import modelx as mx

m, s = mx.new_model(), mx.new_space()

s.new_cells(name="NoArg") # creating a non-arg cells

df = pd.DataFrame({"A": [1,2,3], "B":[4,5,6]})

s.NoArg = df # assign df to NoArg

s.NoArg() # returns df

mx.write_model(m, "NoArg")
m2 = mx.read_model("NoArg")

m2.Space1.NoArg # non-arg cells is restored

m2.Space1.NoArg() # You want this to return df 

Sorry, I misunderstood you earlier: I thought the approach described above works. It seems that even single value stored in the cell without arguments can't be restored:

import modelx as mx
m, s = mx.new_model(), mx.new_space()
s.new_cells(name="NoArg") 
s.NoArg = 1
mx.write_model(m, "NoArg")
m2 = mx.read_model("NoArg")
m2.Space1.NoArg
m2.Space1.NoArg()

It would be really helpful to have this functionality including pandas objects. I won't be able to use write_model feature without it.

alebaran commented 4 years ago

I've also noticed that it isn't possible to have DataFrame as a ref. Is it intentional this way?

fumitoh commented 4 years ago

You can have DFs as refs. You mean you can't write_model DataFrame as ref?

alebaran commented 4 years ago

You can have DFs as refs. You mean you can't write_model DataFrame as ref?

Using your earlier example:

import pandas as pd
import modelx as mx

m, s = mx.new_model(), mx.new_space()

df = pd.DataFrame({"A": [1,2,3], "B":[4,5,6]})

s.NoArg = df # assign df to NoArg

mx.write_model(m, "NoArg")
alebaran commented 4 years ago

Another thing is that the following code, which works with model.save doesn't work with mx.write_model:

import modelx as mx
from datetime import time

m, s = mx.new_model(), mx.new_space()

s.time = time

mx.write_model(m, "NoArg")

There is an easy workaround for this one, hence not important.

fumitoh commented 4 years ago

modelx version 0.1.0 is released, and input values of a cells are distinguished from calculated values, and they are saved by write_model function. See the release note for the details. https://modelx.readthedocs.io/en/latest/releases/relnotes_v0_1_0.html