14
14
15
15
from adaptive .learner .learner1D import Learner1D , _get_intervals
16
16
from adaptive .notebook_integration import ensure_holoviews
17
- from adaptive .types import Real
17
+ from adaptive .types import Int , Real
18
+ from adaptive .utils import assign_defaults , partial_function_from_dataframe
19
+
20
+ try :
21
+ import pandas
22
+
23
+ with_pandas = True
24
+
25
+ except ModuleNotFoundError :
26
+ with_pandas = False
18
27
19
28
Point = Tuple [int , Real ]
20
29
Points = List [Point ]
@@ -127,6 +136,112 @@ def min_samples_per_point(self) -> int:
127
136
return 0
128
137
return min (self ._number_samples .values ())
129
138
139
+ def to_numpy (self , mean : bool = False ) -> np .ndarray :
140
+ if mean :
141
+ return super ().to_numpy ()
142
+ else :
143
+ return np .array (
144
+ [
145
+ (seed , x , * np .atleast_1d (y ))
146
+ for x , seed_y in self ._data_samples .items ()
147
+ for seed , y in seed_y .items ()
148
+ ]
149
+ )
150
+
151
+ def to_dataframe (
152
+ self ,
153
+ mean : bool = False ,
154
+ with_default_function_args : bool = True ,
155
+ function_prefix : str = "function." ,
156
+ seed_name : str = "seed" ,
157
+ x_name : str = "x" ,
158
+ y_name : str = "y" ,
159
+ ) -> pandas .DataFrame :
160
+ """Return the data as a `pandas.DataFrame`.
161
+
162
+ Parameters
163
+ ----------
164
+ with_default_function_args : bool, optional
165
+ Include the ``learner.function``'s default arguments as a
166
+ column, by default True
167
+ function_prefix : str, optional
168
+ Prefix to the ``learner.function``'s default arguments' names,
169
+ by default "function."
170
+ seed_name : str, optional
171
+ Name of the ``seed`` parameter, by default "seed"
172
+ x_name : str, optional
173
+ Name of the ``x`` parameter, by default "x"
174
+ y_name : str, optional
175
+ Name of the output value, by default "y"
176
+
177
+ Returns
178
+ -------
179
+ pandas.DataFrame
180
+
181
+ Raises
182
+ ------
183
+ ImportError
184
+ If `pandas` is not installed.
185
+ """
186
+ if not with_pandas :
187
+ raise ImportError ("pandas is not installed." )
188
+ if mean :
189
+ data = sorted (self .data .items ())
190
+ columns = [x_name , y_name ]
191
+ else :
192
+ data = [
193
+ (seed , x , y )
194
+ for x , seed_y in sorted (self ._data_samples .items ())
195
+ for seed , y in sorted (seed_y .items ())
196
+ ]
197
+ columns = [seed_name , x_name , y_name ]
198
+ df = pandas .DataFrame (data , columns = columns )
199
+ df .attrs ["inputs" ] = [seed_name , x_name ]
200
+ df .attrs ["output" ] = y_name
201
+ if with_default_function_args :
202
+ assign_defaults (self .function , df , function_prefix )
203
+ return df
204
+
205
+ def load_dataframe (
206
+ self ,
207
+ df : pandas .DataFrame ,
208
+ with_default_function_args : bool = True ,
209
+ function_prefix : str = "function." ,
210
+ seed_name : str = "seed" ,
211
+ x_name : str = "x" ,
212
+ y_name : str = "y" ,
213
+ ):
214
+ """Load data from a `pandas.DataFrame`.
215
+
216
+ If ``with_default_function_args`` is True, then ``learner.function``'s
217
+ default arguments are set (using `functools.partial`) from the values
218
+ in the `pandas.DataFrame`.
219
+
220
+ Parameters
221
+ ----------
222
+ df : pandas.DataFrame
223
+ The data to load.
224
+ with_default_function_args : bool, optional
225
+ The ``with_default_function_args`` used in ``to_dataframe()``,
226
+ by default True
227
+ function_prefix : str, optional
228
+ The ``function_prefix`` used in ``to_dataframe``, by default "function."
229
+ seed_name : str, optional
230
+ The ``seed_name`` used in ``to_dataframe``, by default "seed"
231
+ x_name : str, optional
232
+ The ``x_name`` used in ``to_dataframe``, by default "x"
233
+ y_name : str, optional
234
+ The ``y_name`` used in ``to_dataframe``, by default "y"
235
+ """
236
+ # Were using zip instead of df[[seed_name, x_name]].values because that will
237
+ # make the seeds into floats
238
+ seed_x = list (zip (df [seed_name ].values .tolist (), df [x_name ].values .tolist ()))
239
+ self .tell_many (seed_x , df [y_name ].values )
240
+ if with_default_function_args :
241
+ self .function = partial_function_from_dataframe (
242
+ self .function , df , function_prefix
243
+ )
244
+
130
245
def ask (self , n : int , tell_pending : bool = True ) -> tuple [Points , list [float ]]:
131
246
"""Return 'n' points that are expected to maximally reduce the loss."""
132
247
# If some point is undersampled, resample it
@@ -362,7 +477,9 @@ def _calc_error_in_mean(self, ys: Iterable[Real], y_avg: Real, n: int) -> float:
362
477
t_student = scipy .stats .t .ppf (1 - self .alpha , df = n - 1 )
363
478
return t_student * (variance_in_mean / n ) ** 0.5
364
479
365
- def tell_many (self , xs : Points , ys : Sequence [Real ]) -> None :
480
+ def tell_many (
481
+ self , xs : Points | np .ndarray , ys : Sequence [Real ] | np .ndarray
482
+ ) -> None :
366
483
# Check that all x are within the bounds
367
484
# TODO: remove this requirement, all other learners add the data
368
485
# but ignore it going forward.
@@ -373,7 +490,7 @@ def tell_many(self, xs: Points, ys: Sequence[Real]) -> None:
373
490
)
374
491
375
492
# Create a mapping of points to a list of samples
376
- mapping : DefaultDict [Real , DefaultDict [int , Real ]] = defaultdict (
493
+ mapping : DefaultDict [Real , DefaultDict [Int , Real ]] = defaultdict (
377
494
lambda : defaultdict (dict )
378
495
)
379
496
for (seed , x ), y in zip (xs , ys ):
0 commit comments