Skip to content

Commit 0035d8c

Browse files
committed
More efficient dataframe creation from proxy model
1 parent 727802e commit 0035d8c

1 file changed

Lines changed: 41 additions & 31 deletions

File tree

src/petab_gui/views/utils.py

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,43 +3,53 @@
33

44

55
def proxy_to_dataframe(proxy_model):
6+
"""Convert Proxy Model to pandas DataFrame."""
67
rows = proxy_model.rowCount()
78
cols = proxy_model.columnCount()
89

10+
if rows <= 1: # <=1 due to "New row..." in every table
11+
return pd.DataFrame()
12+
913
headers = [proxy_model.headerData(c, Qt.Horizontal) for c in range(cols)]
10-
data = []
1114

15+
# Pre-allocate list of lists (faster than dicts)
16+
data = []
1217
for r in range(rows - 1):
13-
row = {headers[c]: proxy_model.index(r, c).data() for c in range(cols)}
14-
for key, value in row.items():
15-
if isinstance(value, str) and value == "":
16-
row[key] = None
18+
row = []
19+
for c in range(cols):
20+
value = proxy_model.index(r, c).data()
21+
# Convert empty strings to None
22+
row.append(
23+
None if (isinstance(value, str) and value == "") else value
24+
)
1725
data.append(row)
26+
1827
if not data:
1928
return pd.DataFrame()
20-
if proxy_model.source_model.table_type == "condition":
21-
data = pd.DataFrame(data).set_index("conditionId")
22-
elif proxy_model.source_model.table_type == "observable":
23-
data = pd.DataFrame(data).set_index("observableId")
24-
elif proxy_model.source_model.table_type == "parameter":
25-
data = pd.DataFrame(data).set_index("parameterId")
26-
elif proxy_model.source_model.table_type == "measurement":
27-
# turn measurement and time to float
28-
data = pd.DataFrame(data)
29-
data["measurement"] = data["measurement"].astype(float)
30-
data["time"] = data["time"].astype(float)
31-
elif proxy_model.source_model.table_type == "simulation":
32-
# turn simulation and time to float
33-
data = pd.DataFrame(data)
34-
data["simulation"] = data["simulation"].astype(float)
35-
data["time"] = data["time"].astype(float)
36-
elif proxy_model.source_model.table_type == "visualization":
37-
data = pd.DataFrame(data)
38-
if "xOffset" in data.columns:
39-
data["xOffset"] = data["xOffset"].astype(float)
40-
if "yOffset" in data.columns:
41-
data["yOffset"] = data["yOffset"].astype(float)
42-
else:
43-
data = pd.DataFrame(data)
44-
45-
return data
29+
30+
# Create DataFrame in one shot
31+
df = pd.DataFrame(data, columns=headers)
32+
33+
# Apply type-specific transformations
34+
table_type = proxy_model.source_model.table_type
35+
36+
if table_type == "condition":
37+
df = df.set_index("conditionId")
38+
elif table_type == "observable":
39+
df = df.set_index("observableId")
40+
elif table_type == "parameter":
41+
df = df.set_index("parameterId")
42+
elif table_type == "measurement":
43+
# Use pd.to_numeric with errors='coerce' for robust conversion
44+
df["measurement"] = pd.to_numeric(df["measurement"], errors="coerce")
45+
df["time"] = pd.to_numeric(df["time"], errors="coerce")
46+
elif table_type == "simulation":
47+
df["simulation"] = pd.to_numeric(df["simulation"], errors="coerce")
48+
df["time"] = pd.to_numeric(df["time"], errors="coerce")
49+
elif table_type == "visualization":
50+
if "xOffset" in df.columns:
51+
df["xOffset"] = pd.to_numeric(df["xOffset"], errors="coerce")
52+
if "yOffset" in df.columns:
53+
df["yOffset"] = pd.to_numeric(df["yOffset"], errors="coerce")
54+
55+
return df

0 commit comments

Comments
 (0)