Closed Xtreme-G closed 5 years ago
From the first error message it looks like you are trying to assign data from a pandas.DataFrame without setting column names. By specifying the column name with columns=['value']
it should work. From the second error message it looks like you specified only one column as index and two columns as data.
The following example works with amplpy v0.6.1 and shows how to assign data from a pandas.DataFrame and from an amplpy.DataFrame:
from amplpy import AMPL, DataFrame
import pandas as pd
ampl = AMPL()
ampl.eval('''
set someSet := 1..100;
param N := 5;
param x{someSet, 1..N} default 0;
''')
x_values = {
(1, 1): 3,
(6, 3): -1,
(99, 5): 15,
}
df = pd.DataFrame.from_dict(x_values, orient='index', columns=['value'])
print('df:', df)
ampl.param['x'] = df
ampl.display('x')
df1 = DataFrame(('i0', 'i1'), ('value'))
df1.addRow(30, 3, 23)
df1.addRow(25, 1, 9)
ampl.param['x'] = df1
ampl.display('x')
I was a little vague on what I was trying to do exactly. It was to index the dataframe by my set and use integer columns for 1..N. This did not work, but your answer led me in the right direction.
from amplpy import AMPL, DataFrame
import pandas as pd
ampl = AMPL()
ampl.eval('''
set someSet := {"First", "Second"};
param N := 5;
param x{someSet, 1..N} default 0;
''')
df = pd.DataFrame([[1,2,3,4,5], [6,7,8,9,0]], index=['First', 'Second'], columns=[1,2,3,4,5])
print('df:', df)
ampl.param['x'] = pd.DataFrame.from_dict(df.stack().to_dict(), orient='index', columns=['v'])
ampl.display('x')
Thank you!
Just one minor note: you could also use ampl.param['x'] = df.stack().to_dict()
to perform the assignment directly from a dictionary so that you don't need to create a new Pandas DataFrame. Moreover, we are planning to convert numeric column names into string column names automatically in the next bugfix release so that you would be able to do the following ampl.param['x'] = df.stack()
(still not valid at the moment).
If you install amplpy v0.6.2b0 (pip install amplpy --upgrade --pre), you should now be able to do the following:
from amplpy import AMPL, DataFrame
import pandas as pd
ampl = AMPL()
ampl.eval('''
set someSet := {"First", "Second"};
param N := 5;
param x1{someSet, 1..N} default 0;
param x2{someSet, 1..N} default 0;
param x3{someSet, 1..N} default 0;
param x4{someSet, 1..N} default 0;
''')
df = pd.DataFrame([
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 0]
],
index=['First', 'Second'],
columns=[1, 2, 3, 4, 5]
)
ampl.param['x1'] = pd.DataFrame.from_dict(
df.stack().to_dict(),
orient='index',
columns=['v']
)
ampl.param['x2'] = pd.DataFrame(df.stack())
ampl.param['x3'] = df.stack().to_dict()
ampl.param['x4'] = df.stack()
d1 = ampl.param['x1'].getValues().toDict()
d2 = ampl.param['x2'].getValues().toDict()
d3 = ampl.param['x3'].getValues().toDict()
d4 = ampl.param['x4'].getValues().toDict()
print(d1)
print(d2)
print(d3)
print(d4)
assert d1 == d2 == d3 == d4
Setting through a pandas Dataframe fails due to:
Setting through an AMPL dataframe created from numpy fails due do: