File qt_plot.py changed (mode: 100644) (index f4ef829..758936d) |
... |
... |
import pandas as pd # required for estimation graph |
12 |
12 |
|
|
13 |
13 |
from . import estimation as stm |
from . import estimation as stm |
14 |
14 |
from . import misc |
from . import misc |
15 |
|
|
|
|
15 |
|
from . import stm_df |
16 |
16 |
|
|
17 |
17 |
def qt_gui_plot_2d(sample_box, space='R', *args, **kwargs): |
def qt_gui_plot_2d(sample_box, space='R', *args, **kwargs): |
18 |
18 |
""" |
""" |
|
... |
... |
class QtGuiPlot2D(QtGui.QMainWindow): |
188 |
188 |
self.tabifyDockWidget(self.dockables[0], dock) |
self.tabifyDockWidget(self.dockables[0], dock) |
189 |
189 |
|
|
190 |
190 |
dock = QtGui.QDockWidget("Simplex error graph", self) |
dock = QtGui.QDockWidget("Simplex error graph", self) |
191 |
|
dock.setWidget(SimplexErrorGraph(self.sample_box, self, dock)) |
|
|
191 |
|
dock.setWidget(SimplexErrorGraph(self.simplex_data, dock)) |
192 |
192 |
self.dockables.append(dock) |
self.dockables.append(dock) |
193 |
193 |
self.tabifyDockWidget(self.dockables[0], dock) |
self.tabifyDockWidget(self.dockables[0], dock) |
194 |
194 |
|
|
|
... |
... |
class Isocurves: |
624 |
624 |
self.on_space_changed() |
self.on_space_changed() |
625 |
625 |
|
|
626 |
626 |
def on_space_changed(self): |
def on_space_changed(self): |
627 |
|
points = getattr(self.f, self.w.space) |
|
|
627 |
|
if self.contour_item.checkState() or self.isocurve_item.checkState(): |
|
628 |
|
points = getattr(self.f, self.w.space) |
|
629 |
|
|
|
630 |
|
#č valčím s nekoněčno |
|
631 |
|
mask = np.all(np.isfinite(points), axis=1) |
628 |
632 |
|
|
629 |
|
#č valčím s nekoněčno |
|
630 |
|
mask = np.all(np.isfinite(points), axis=1) |
|
631 |
|
|
|
632 |
|
self.max = np.max(points[mask], axis=0) |
|
633 |
|
self.min = np.min(points[mask], axis=0) |
|
634 |
|
|
|
635 |
|
ngrid = self.ngrid |
|
636 |
|
grid = np.mgrid[0:ngrid,0:ngrid].T.reshape(-1, 2) |
|
637 |
|
# scale |
|
638 |
|
grid = self.grid_scale(grid) |
|
|
633 |
|
self.max = np.max(points[mask], axis=0) |
|
634 |
|
self.min = np.min(points[mask], axis=0) |
639 |
635 |
|
|
640 |
|
f_model = self.w.sample_box.f_model |
|
641 |
|
self.pdf = f_model.sample_pdf(grid, space=self.w.space) |
|
642 |
|
#č pokud tam budou nanka, pak nikdo nic nedostane |
|
643 |
|
#č u současných f_modelů však nemají být |
|
644 |
|
self.pdf = np.nan_to_num(self.pdf, copy=False) |
|
645 |
|
#č reshape, flip a rot90 dle dokumentaci vracej view |
|
646 |
|
#č povede-li to numpy, data nebudou žrat další místo v paměti |
|
647 |
|
self.data = self.pdf.reshape((ngrid, ngrid)) |
|
648 |
|
#č bůhví co ta pomocná funkce očekává za vstup |
|
649 |
|
#č a co je zvykem u těch borců co pracujou s obrázky |
|
650 |
|
#č zkrátka, empiricky - buď zde flipnout a pootočit |
|
651 |
|
#č nebo tam dále prohodit souřadnice |
|
652 |
|
self.data = np.flip(self.data, axis=0) |
|
653 |
|
self.data = np.rot90(self.data, k=-1) |
|
|
636 |
|
ngrid = self.ngrid |
|
637 |
|
grid = np.mgrid[0:ngrid,0:ngrid].T.reshape(-1, 2) |
|
638 |
|
# scale |
|
639 |
|
grid = self.grid_scale(grid) |
654 |
640 |
|
|
|
641 |
|
f_model = self.w.sample_box.f_model |
|
642 |
|
self.pdf = f_model.sample_pdf(grid, space=self.w.space) |
|
643 |
|
#č pokud tam budou nanka, pak nikdo nic nedostane |
|
644 |
|
#č u současných f_modelů však nemají být |
|
645 |
|
self.pdf = np.nan_to_num(self.pdf, copy=False) |
|
646 |
|
#č reshape, flip a rot90 dle dokumentaci vracej view |
|
647 |
|
#č povede-li to numpy, data nebudou žrat další místo v paměti |
|
648 |
|
self.data = self.pdf.reshape((ngrid, ngrid)) |
|
649 |
|
#č bůhví co ta pomocná funkce očekává za vstup |
|
650 |
|
#č a co je zvykem u těch borců co pracujou s obrázky |
|
651 |
|
#č zkrátka, empiricky - buď zde flipnout a pootočit |
|
652 |
|
#č nebo tam dále prohodit souřadnice |
|
653 |
|
self.data = np.flip(self.data, axis=0) |
|
654 |
|
self.data = np.rot90(self.data, k=-1) |
655 |
655 |
|
|
656 |
|
self.plot() |
|
|
656 |
|
|
|
657 |
|
self.plot() |
657 |
658 |
|
|
658 |
659 |
|
|
659 |
660 |
def show_slot(self, item): |
def show_slot(self, item): |
|
... |
... |
class SimplexEstimationData(QtCore.QObject): |
1037 |
1038 |
|
|
1038 |
1039 |
self.simplex_chk = QtGui.QAction("Simplex estimations", self.TRI_menu) |
self.simplex_chk = QtGui.QAction("Simplex estimations", self.TRI_menu) |
1039 |
1040 |
self.simplex_chk.setCheckable(True) |
self.simplex_chk.setCheckable(True) |
1040 |
|
#self.simplex_chk.setChecked(True) |
|
|
1041 |
|
self.simplex_chk.setChecked(True) |
1041 |
1042 |
self.simplex_chk.triggered.connect(self.recalculate) |
self.simplex_chk.triggered.connect(self.recalculate) |
1042 |
1043 |
self.TRI_menu.addAction(self.simplex_chk) |
self.TRI_menu.addAction(self.simplex_chk) |
1043 |
1044 |
|
|
1044 |
|
# hope, it is temporary |
|
1045 |
|
self.sources_action_group = QtGui.QActionGroup(self.TRI_menu) |
|
1046 |
|
self.sources_action_group.addAction(self.TRI_overall_chk) |
|
1047 |
|
self.sources_action_group.addAction(self.simplex_chk) |
|
|
1045 |
|
# year, it was |
|
1046 |
|
## hope, it is temporary |
|
1047 |
|
#self.sources_action_group = QtGui.QActionGroup(self.TRI_menu) |
|
1048 |
|
#self.sources_action_group.addAction(self.TRI_overall_chk) |
|
1049 |
|
#self.sources_action_group.addAction(self.simplex_chk) |
1048 |
1050 |
|
|
1049 |
1051 |
self.TRI_menu.addSeparator() |
self.TRI_menu.addSeparator() |
1050 |
1052 |
|
|
1051 |
1053 |
self.proxy_chk = QtGui.QAction("Proxy", self.TRI_menu) |
self.proxy_chk = QtGui.QAction("Proxy", self.TRI_menu) |
1052 |
1054 |
self.proxy_chk.setCheckable(True) |
self.proxy_chk.setCheckable(True) |
|
1055 |
|
self.proxy_chk.setChecked(hasattr(self.dice_box, 'proxy')) |
1053 |
1056 |
self.proxy_chk.triggered.connect(self.recalculate) |
self.proxy_chk.triggered.connect(self.recalculate) |
1054 |
1057 |
self.TRI_menu.addAction(self.proxy_chk) |
self.TRI_menu.addAction(self.proxy_chk) |
1055 |
1058 |
|
|
|
... |
... |
class SimplexEstimationData(QtCore.QObject): |
1073 |
1076 |
proposal_filename += '.xlsx' |
proposal_filename += '.xlsx' |
1074 |
1077 |
else: |
else: |
1075 |
1078 |
proposal_filename = self.dice_box.gm_signature + '.xlsx' |
proposal_filename = self.dice_box.gm_signature + '.xlsx' |
1076 |
|
filename, *__ = pg.FileDialog.getSaveFileName(self, 'Export to Excel',\ |
|
|
1079 |
|
filename, *__ = pg.FileDialog.getSaveFileName(self.stream, 'Export to Excel',\ |
1077 |
1080 |
proposal_filename, initialFilter='*.xlsx') |
proposal_filename, initialFilter='*.xlsx') |
1078 |
1081 |
self.df.to_excel(filename) |
self.df.to_excel(filename) |
1079 |
1082 |
except BaseException as e: |
except BaseException as e: |
|
... |
... |
class SimplexEstimationData(QtCore.QObject): |
1081 |
1084 |
|
|
1082 |
1085 |
|
|
1083 |
1086 |
def recalculate(self): |
def recalculate(self): |
1084 |
|
if self.simplex_chk.isChecked(): |
|
1085 |
|
tri_estimation = dict() |
|
1086 |
|
try: # тут всё что угодно может пойти не так |
|
1087 |
|
# kruci, ještě navic i generovať pokažde znovu... |
|
1088 |
|
|
|
1089 |
|
# new-style: šecko leží dohromady a každý si z toho |
|
1090 |
|
# bere co chce a jak chce |
|
1091 |
|
# ne že by to bylo nějak šetrný |
|
1092 |
|
# estimation je slovníkem |
|
1093 |
|
for estimation in self.dice_box.estimations: |
|
1094 |
|
# nsim musí mäť každej odhad |
|
1095 |
|
# pokud nemá - je třeba jej prostě opravit |
|
1096 |
|
nsim = estimation['nsim'] |
|
1097 |
|
try: |
|
1098 |
|
tri_estimation[nsim] = estimation['TRI_estimation'] |
|
1099 |
|
except KeyError as e: |
|
1100 |
|
pass #print(self.__class__.__name__ + ":", repr(e)) |
|
1101 |
|
|
|
1102 |
|
#č neotravuj uživatele chybovejma hlaškama |
|
1103 |
|
if tri_estimation: |
|
1104 |
|
# it can be effectively done with pandas |
|
1105 |
|
self.df = df = pd.DataFrame(tuple(tri_estimation.values())) |
|
1106 |
|
# -1 = 'out', 0=success, 1=failure, 2=mix |
|
1107 |
|
df.rename(columns={-1:'out', 0:'success', 1:'failure', 2:'mix'}, inplace=True) |
|
1108 |
|
df.insert(loc=0, column='nsim', value=tuple(tri_estimation.keys()), allow_duplicates=False) |
|
1109 |
|
df.sort_values('nsim', inplace=True) |
|
1110 |
|
|
|
1111 |
|
self._pens_data_update() |
|
|
1087 |
|
try: |
|
1088 |
|
# sources=['box', 'user'] |
|
1089 |
|
sources = list() |
|
1090 |
|
if self.TRI_overall_chk.isChecked(): |
|
1091 |
|
sources.append('box') |
|
1092 |
|
if self.simplex_chk.isChecked(): |
|
1093 |
|
sources.append('user') |
1112 |
1094 |
|
|
1113 |
|
nsim, y = get_estimation_data(self.dice_box.estimations, 'vertex_estimation') |
|
1114 |
|
df['vertex_estimation'] = y #č spolehám na konzistenci odhadů (ne úplně) |
|
1115 |
|
self.pen_vertex.setData(*self.zerosafe(self.proxy(nsim), y)) |
|
1116 |
|
|
|
1117 |
|
nsim, y = get_estimation_data(self.dice_box.estimations, 'weighted_vertex_estimation') |
|
1118 |
|
df['weighted_vertex_estimation'] = y #č spolehám na konzistenci odhadů (ne úplně) |
|
1119 |
|
self.pen_weighted_vertex.setData(*self.zerosafe(self.proxy(nsim), y)) |
|
1120 |
|
except: |
|
1121 |
|
pass |
|
1122 |
|
self.simplex_estimation_updated.emit() |
|
|
1095 |
|
self.df = stm_df.get_tri_data_frame(self.dice_box, sources=sources,\ |
|
1096 |
|
apply_proxy=self.proxy_chk.isChecked()) |
|
1097 |
|
self.simplex_estimation_updated.emit() |
|
1098 |
|
|
|
1099 |
|
except BaseException as e: |
|
1100 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
1101 |
|
|
1123 |
1102 |
|
|
1124 |
1103 |
|
|
1125 |
1104 |
class SimplexEstimationGraph(pg.PlotWidget): |
class SimplexEstimationGraph(pg.PlotWidget): |
|
... |
... |
class SimplexEstimationGraph(pg.PlotWidget): |
1370 |
1349 |
|
|
1371 |
1350 |
|
|
1372 |
1351 |
|
|
1373 |
|
class SimplexErrorGraph(SimplexEstimationGraph): |
|
1374 |
|
pass |
|
|
1352 |
|
class SimplexErrorGraph(pg.PlotWidget): |
|
1353 |
|
def __init__(self, simplex_data, parent=None, *args, **kwargs): |
|
1354 |
|
super().__init__(parent, *args, **kwargs) |
|
1355 |
|
self.simplex_data = simplex_data |
|
1356 |
|
self.simplex_data.simplex_estimation_updated.connect(self.redraw) |
|
1357 |
|
|
|
1358 |
|
self.setup_context_menu() |
|
1359 |
|
self.setup() |
|
1360 |
|
|
|
1361 |
|
def setup_context_menu(self): |
|
1362 |
|
# creates instance of LegendItem |
|
1363 |
|
# and saves it into plotItem.legend |
|
1364 |
|
self.legend = self.addLegend() |
|
1365 |
|
|
|
1366 |
|
self.plotItem.ctrl.xGridCheck.setChecked(True) |
|
1367 |
|
self.plotItem.ctrl.yGridCheck.setChecked(True) |
|
1368 |
|
|
|
1369 |
|
# menu of SimplexEstimationData |
|
1370 |
|
self.plotItem.vb.menu.addMenu(self.simplex_data.TRI_menu) |
|
1371 |
|
|
|
1372 |
|
#č já se bojím. radší to uložím |
|
1373 |
|
self.custom_menu = self.plotItem.vb.menu.addMenu("Error graph") |
|
1374 |
|
|
|
1375 |
|
self.legend_chk = QtGui.QAction("Legend", self.custom_menu) |
|
1376 |
|
self.legend_chk.setCheckable(True) |
|
1377 |
|
self.legend_chk.triggered.connect(lambda: self.legend.setVisible(self.legend_chk.isChecked())) |
|
1378 |
|
self.custom_menu.addAction(self.legend_chk) |
|
1379 |
|
# apply custom menu option |
|
1380 |
|
self.legend.setVisible(self.legend_chk.isChecked()) |
|
1381 |
|
|
|
1382 |
|
self.laction = QtGui.QAction("Show labels", self.custom_menu) |
|
1383 |
|
self.laction.triggered.connect(self.show_labels) |
|
1384 |
|
self.custom_menu.addAction(self.laction) |
|
1385 |
|
|
|
1386 |
|
|
|
1387 |
|
def show_labels(self): |
|
1388 |
|
self.setLabel('left', "Failure probability estimation error") |
|
1389 |
|
self.setLabel('bottom', "Number of simulations") |
|
1390 |
|
|
|
1391 |
|
|
|
1392 |
|
def setup(self, *args, **kwargs): |
|
1393 |
|
self.clear() |
|
1394 |
|
self.setBackground('w') |
|
1395 |
|
x = y = () # zde jen vytvoříme kostru, nakrmime daty v .redraw() |
|
1396 |
|
|
|
1397 |
|
# We will use logMode by default |
|
1398 |
|
self.setLogMode(y=True) |
|
1399 |
|
|
|
1400 |
|
#xkcd_red = (253, 193, 197) # xkcd: pale rose (#fdc1c5) |
|
1401 |
|
#red = (253, 0, 17, 96) |
|
1402 |
|
|
|
1403 |
|
#self.pen_f = self.plot(x, y, brush=red)#, name="failure domain estimation") |
|
1404 |
|
#self.pen_f.setZValue(-100) |
|
1405 |
|
|
|
1406 |
|
|
|
1407 |
|
pen = pg.mkPen(color='m', width=2) |
|
1408 |
|
self.pen_vertex = self.plot(x, y, pen=pen, name="simple pf estimation") |
|
1409 |
|
pen = pg.mkPen(color='r', width=2) #(118, 187, 255) |
|
1410 |
|
self.pen_weighted_vertex = self.plot(x, y, pen=pen, name="weighted pf estimation") |
|
1411 |
|
|
|
1412 |
|
|
|
1413 |
|
|
|
1414 |
|
#č když se někde objeví nula se zapnutým LogModem - |
|
1415 |
|
#č qtpygraph hned spadne a není možne ten pad zachytit |
|
1416 |
|
def zerosafe(self, x, y, fallback_y=None): |
|
1417 |
|
x = np.array(x) |
|
1418 |
|
y = np.array(y) |
|
1419 |
|
if fallback_y is None: |
|
1420 |
|
fallback_y = y |
|
1421 |
|
y = np.where(y > 0, y, fallback_y) |
|
1422 |
|
mask = y > 0 |
|
1423 |
|
return x[mask], y[mask] |
|
1424 |
|
|
|
1425 |
|
|
|
1426 |
|
def redraw(self): |
|
1427 |
|
#č neotravujme uživatele chybovejma hlaškama |
|
1428 |
|
if hasattr(self.simplex_data.dice_box, 'pf_exact'): |
|
1429 |
|
try: #ё тут всё что угодно может пойти не так |
|
1430 |
|
pf_exact = self.simplex_data.dice_box.pf_exact |
|
1431 |
|
|
|
1432 |
|
df = self.simplex_data.df |
|
1433 |
|
#č zapíšeme do data rámu, snad nikomu nebude vadit |
|
1434 |
|
df['vertex_estimation_error'] = df['vertex_estimation'] - pf_exact |
|
1435 |
|
df['weighted_vertex_estimation_error'] = df['weighted_vertex_estimation'] - pf_exact |
|
1436 |
|
|
|
1437 |
|
v = df['vertex_estimation_error'].abs() |
|
1438 |
|
wv = df['weighted_vertex_estimation_error'].abs() |
|
1439 |
|
|
|
1440 |
|
x, y = self.zerosafe(v.index, v.to_numpy()) |
|
1441 |
|
self.pen_vertex.setData(x, y) |
|
1442 |
|
|
|
1443 |
|
x, y = self.zerosafe(wv.index, wv.to_numpy()) |
|
1444 |
|
self.pen_weighted_vertex.setData(x, y) |
|
1445 |
|
|
|
1446 |
|
|
|
1447 |
|
except BaseException as e: |
|
1448 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
1449 |
|
|
|
1450 |
|
|
|
1451 |
|
|
1375 |
1452 |
|
|
1376 |
1453 |
|
|
1377 |
1454 |
|
|
File stm_df.py changed (mode: 100644) (index b1c9dca..408e989) |
5 |
5 |
tohle je mezivrstva mezi simplexovymi odhady v boxu a grafy v qt_plot |
tohle je mezivrstva mezi simplexovymi odhady v boxu a grafy v qt_plot |
6 |
6 |
(Kdybych věřil, že je to jen pro qt_plot, tak ten modul nevytvařím) |
(Kdybych věřil, že je to jen pro qt_plot, tak ten modul nevytvařím) |
7 |
7 |
|
|
8 |
|
Podle kódu pyqtgraph a matplotlib už je jasný, že musím vracet 2 numpy vektory. |
|
9 |
|
Asi nebudu zahrnovat .zerosafe() - je to jen zvlaštnost pyqtgraph |
|
10 |
|
Není úplně jasně, zda mám dělat třídu (stateful), |
|
11 |
|
nebo mám se omezit jen na funkci (stateless) |
|
12 |
|
Minule přišel jsem na potřebu stateful, |
|
13 |
|
ale už si nepamatuji proč. |
|
|
8 |
|
#Podle kódu pyqtgraph a matplotlib už je jasný, že musím vracet 2 numpy vektory. |
|
9 |
|
#Asi nebudu zahrnovat .zerosafe() - je to jen zvlaštnost pyqtgraph |
|
10 |
|
#Není úplně jasně, zda mám dělat třídu (stateful), |
|
11 |
|
#nebo mám se omezit jen na funkci (stateless) |
|
12 |
|
#Minule přišel jsem na potřebu stateful, |
|
13 |
|
#ale už si nepamatuji proč. |
14 |
14 |
|
|
|
15 |
|
není aktuální, ale ty estimátory furt nemám promyšlený. |
|
16 |
|
Podstata problému spočívá v tom, že současný DiceBox |
|
17 |
|
ukladá odhady dvěma různejma způsoby, přičemž |
|
18 |
|
TRI odhady jsou ukladány jako slovníky (strukturováně). |
|
19 |
|
Pro ty strukturovaná data Pandas (aj obecně tabulka) |
|
20 |
|
není ideální volba. Na druhou stranu chceme jednoduše |
|
21 |
|
všechno co máme nakreslit a vyexportovat do Excelu. |
15 |
22 |
""" |
""" |
16 |
23 |
|
|
17 |
24 |
import numpy as np |
import numpy as np |
18 |
|
import pandas as pd |
|
|
25 |
|
#č právě kvůli pandas davam tohle do separatního modulu |
|
26 |
|
#č normálně kód WellMet pandas nevyžaduje |
|
27 |
|
import pandas as pd |
19 |
28 |
|
|
20 |
29 |
|
|
21 |
30 |
def get_estimation_data(estimations, metric): |
def get_estimation_data(estimations, metric): |
|
... |
... |
def get_tri_data_frame(dice_box, sources=['box', 'user'], apply_proxy=False): |
81 |
90 |
|
|
82 |
91 |
#č předbežně: |
#č předbežně: |
83 |
92 |
#č nejdřív concat (spojime zdroje dohromady) |
#č nejdřív concat (spojime zdroje dohromady) |
84 |
|
df = pd.concat((df_box, df_user)) |
|
|
93 |
|
df = pd.concat((df_box, df_user), sort=False) |
85 |
94 |
|
|
86 |
95 |
#č pak deduplicate |
#č pak deduplicate |
87 |
96 |
#č (aby se převzaly odhady se stejným nsim z posledního zdroje) |
#č (aby se převzaly odhady se stejným nsim z posledního zdroje) |
|
... |
... |
def get_tri_data_frame(dice_box, sources=['box', 'user'], apply_proxy=False): |
98 |
107 |
#č oboje nsim a nsim_proxy jsou pro lide, aby zahrivalo srdce |
#č oboje nsim a nsim_proxy jsou pro lide, aby zahrivalo srdce |
99 |
108 |
#č předpokladá se, že volající kód bude použivat index |
#č předpokladá se, že volající kód bude použivat index |
100 |
109 |
df.insert(loc=0, column='nsim (proxy)', value=nsim_proxy) |
df.insert(loc=0, column='nsim (proxy)', value=nsim_proxy) |
|
110 |
|
#č nahradit index, pak vyhodit ďupy |
101 |
111 |
df.index = nsim_proxy |
df.index = nsim_proxy |
|
112 |
|
df = df.groupby(level=0).last() |
102 |
113 |
|
|
103 |
114 |
#č když ne - tak jenom nahradíme index a vypadneme otsuď |
#č když ne - tak jenom nahradíme index a vypadneme otsuď |
104 |
115 |
#č Alexi, co? vždyť ten index už nemusíme řešit, ten musí bejt v pořádku! |
#č Alexi, co? vždyť ten index už nemusíme řešit, ten musí bejt v pořádku! |
|
... |
... |
def get_tri_box_df(dice_box, tri_estimation_name='TRI_overall_estimations'): |
116 |
127 |
data = dice_box.guessbox.estimations[tri_estimation_name] |
data = dice_box.guessbox.estimations[tri_estimation_name] |
117 |
128 |
nsim, tri_data = data |
nsim, tri_data = data |
118 |
129 |
# it can be effectively done with pandas |
# it can be effectively done with pandas |
119 |
|
self.df = df = pd.DataFrame(tri_data, index=nsim) |
|
|
130 |
|
df = pd.DataFrame(tri_data, index=nsim) |
120 |
131 |
# -1 = 'out', 0=success, 1=failure, 2=mix |
# -1 = 'out', 0=success, 1=failure, 2=mix |
121 |
132 |
df.rename(columns={-1:'out', 0:'success', 1:'failure', 2:'mix'}, inplace=True) |
df.rename(columns={-1:'out', 0:'success', 1:'failure', 2:'mix'}, inplace=True) |
122 |
133 |
df.insert(loc=0, column='nsim', value=nsim) |
df.insert(loc=0, column='nsim', value=nsim) |