@@ -283,3 +283,270 @@ def test_different_modes(self):
283283 mode = mode ,
284284 )
285285 self .assertEqual (seq .mode , mode )
286+
287+ def test_from_df_basic (self ):
288+ """Test from_df with basic parameters."""
289+ df = pd .DataFrame (
290+ {
291+ "date" : pd .date_range ("2023-01-01" , periods = 100 , freq = "D" ),
292+ "value" : np .random .randn (100 ).cumsum (),
293+ }
294+ )
295+
296+ seq = TimeSeriesSequence .from_df (
297+ df ,
298+ time_col = "date" ,
299+ target_col = "value" ,
300+ train_length = 10 ,
301+ predict_length = 5 ,
302+ )
303+
304+ self .assertEqual (seq .train_sequence_length , 10 )
305+ self .assertEqual (seq .predict_sequence_length , 5 )
306+ self .assertGreater (len (seq .sequences ), 0 )
307+
308+ def test_from_df_with_index (self ):
309+ """Test from_df using DataFrame index as time column."""
310+ df = pd .DataFrame (
311+ {
312+ "value" : np .random .randn (100 ).cumsum (),
313+ },
314+ index = pd .date_range ("2023-01-01" , periods = 100 , freq = "D" ),
315+ )
316+
317+ seq = TimeSeriesSequence .from_df (
318+ df ,
319+ target_col = "value" ,
320+ train_length = 10 ,
321+ predict_length = 5 ,
322+ )
323+
324+ self .assertEqual (seq .train_sequence_length , 10 )
325+ self .assertEqual (seq .predict_sequence_length , 5 )
326+ self .assertGreater (len (seq .sequences ), 0 )
327+
328+ def test_from_df_with_groups (self ):
329+ """Test from_df with grouped time series."""
330+ df = pd .DataFrame (
331+ {
332+ "date" : pd .date_range ("2023-01-01" , periods = 200 , freq = "D" ).tolist () * 2 ,
333+ "group" : ["A" ] * 200 + ["B" ] * 200 ,
334+ "value" : np .random .randn (400 ).cumsum (),
335+ }
336+ )
337+
338+ seq = TimeSeriesSequence .from_df (
339+ df ,
340+ time_col = "date" ,
341+ target_col = "value" ,
342+ group_col = "group" ,
343+ train_length = 10 ,
344+ predict_length = 5 ,
345+ )
346+
347+ self .assertEqual (seq .group_ids , ["group" ])
348+ self .assertGreater (len (seq .sequences ), 0 )
349+
350+ def test_from_df_multiple_targets (self ):
351+ """Test from_df with multiple target columns."""
352+ df = pd .DataFrame (
353+ {
354+ "date" : pd .date_range ("2023-01-01" , periods = 100 , freq = "D" ),
355+ "value1" : np .random .randn (100 ).cumsum (),
356+ "value2" : np .random .randn (100 ).cumsum (),
357+ }
358+ )
359+
360+ seq = TimeSeriesSequence .from_df (
361+ df ,
362+ time_col = "date" ,
363+ target_col = ["value1" , "value2" ],
364+ train_length = 10 ,
365+ predict_length = 5 ,
366+ )
367+
368+ self .assertEqual (len (seq .target ), 2 )
369+ self .assertIn ("value1" , seq .target )
370+ self .assertIn ("value2" , seq .target )
371+
372+ def test_from_df_fill_missing_dates (self ):
373+ """Test from_df with missing date filling."""
374+ # Create data with missing dates
375+ dates = pd .date_range ("2023-01-01" , periods = 100 , freq = "D" )
376+ # Remove some dates
377+ dates_with_gaps = dates .delete ([10 , 20 , 30 , 40 ])
378+
379+ df = pd .DataFrame (
380+ {
381+ "date" : dates_with_gaps ,
382+ "value" : np .random .randn (len (dates_with_gaps )).cumsum (),
383+ }
384+ )
385+
386+ seq = TimeSeriesSequence .from_df (
387+ df ,
388+ time_col = "date" ,
389+ target_col = "value" ,
390+ train_length = 10 ,
391+ predict_length = 5 ,
392+ fill_missing_dates = True ,
393+ freq = "D" ,
394+ )
395+
396+ # Should have filled the missing dates
397+ self .assertEqual (len (seq .data ), 100 )
398+
399+ def test_from_df_fillna (self ):
400+ """Test from_df with NaN filling."""
401+ df = pd .DataFrame (
402+ {
403+ "date" : pd .date_range ("2023-01-01" , periods = 100 , freq = "D" ),
404+ "value" : np .random .randn (100 ).cumsum (),
405+ }
406+ )
407+ # Add some NaN values
408+ df .loc [10 :15 , "value" ] = np .nan
409+
410+ seq = TimeSeriesSequence .from_df (
411+ df ,
412+ time_col = "date" ,
413+ target_col = "value" ,
414+ train_length = 10 ,
415+ predict_length = 5 ,
416+ fillna_value = 0.0 ,
417+ )
418+
419+ # Check that NaN values were filled
420+ self .assertFalse (seq .data ["value" ].isna ().any ())
421+
422+ def test_from_df_with_feature_config (self ):
423+ """Test from_df with feature configuration."""
424+ df = pd .DataFrame (
425+ {
426+ "date" : pd .date_range ("2023-01-01" , periods = 100 , freq = "D" ),
427+ "value" : np .random .randn (100 ).cumsum (),
428+ }
429+ )
430+
431+ feature_config = {
432+ "date_features" : {
433+ "type" : "datetime" ,
434+ "features" : ["dayofweek" , "month" ],
435+ "time_col" : "date" ,
436+ }
437+ }
438+
439+ seq = TimeSeriesSequence .from_df (
440+ df ,
441+ time_col = "date" ,
442+ target_col = "value" ,
443+ train_length = 10 ,
444+ predict_length = 5 ,
445+ feature_config = feature_config ,
446+ )
447+
448+ # Check if datetime features were added
449+ self .assertTrue (any (col .startswith ("date_" ) for col in seq .data .columns ))
450+
451+ def test_from_df_validation_errors (self ):
452+ """Test from_df validation errors."""
453+ df = pd .DataFrame (
454+ {
455+ "date" : pd .date_range ("2023-01-01" , periods = 100 , freq = "D" ),
456+ "value" : np .random .randn (100 ).cumsum (),
457+ }
458+ )
459+
460+ # Test missing target_col
461+ with self .assertRaises (ValueError ):
462+ TimeSeriesSequence .from_df (
463+ df ,
464+ time_col = "date" ,
465+ train_length = 10 ,
466+ )
467+
468+ # Test missing train_length
469+ with self .assertRaises (ValueError ):
470+ TimeSeriesSequence .from_df (
471+ df ,
472+ time_col = "date" ,
473+ target_col = "value" ,
474+ )
475+
476+ # Test invalid time_col
477+ with self .assertRaises (KeyError ):
478+ TimeSeriesSequence .from_df (
479+ df ,
480+ time_col = "invalid_col" ,
481+ target_col = "value" ,
482+ train_length = 10 ,
483+ )
484+
485+ # Test invalid target_col
486+ with self .assertRaises (KeyError ):
487+ TimeSeriesSequence .from_df (
488+ df ,
489+ time_col = "date" ,
490+ target_col = "invalid_col" ,
491+ train_length = 10 ,
492+ )
493+
494+ # Test insufficient data length
495+ with self .assertRaises (ValueError ):
496+ TimeSeriesSequence .from_df (
497+ df ,
498+ time_col = "date" ,
499+ target_col = "value" ,
500+ train_length = 90 ,
501+ predict_length = 20 ,
502+ )
503+
504+ def test_from_df_numeric_time_index (self ):
505+ """Test from_df with numeric time index."""
506+ df = pd .DataFrame (
507+ {
508+ "time" : range (100 ),
509+ "value" : np .random .randn (100 ).cumsum (),
510+ }
511+ )
512+
513+ seq = TimeSeriesSequence .from_df (
514+ df ,
515+ time_col = "time" ,
516+ target_col = "value" ,
517+ train_length = 10 ,
518+ predict_length = 5 ,
519+ )
520+
521+ self .assertEqual (seq .train_sequence_length , 10 )
522+ self .assertGreater (len (seq .sequences ), 0 )
523+
524+ def test_from_df_with_stride (self ):
525+ """Test from_df with custom stride."""
526+ df = pd .DataFrame (
527+ {
528+ "date" : pd .date_range ("2023-01-01" , periods = 100 , freq = "D" ),
529+ "value" : np .random .randn (100 ).cumsum (),
530+ }
531+ )
532+
533+ seq = TimeSeriesSequence .from_df (
534+ df ,
535+ time_col = "date" ,
536+ target_col = "value" ,
537+ train_length = 10 ,
538+ predict_length = 5 ,
539+ stride = 2 ,
540+ )
541+
542+ self .assertEqual (seq .stride , 2 )
543+ # With stride=2, we should have fewer sequences
544+ seq_stride1 = TimeSeriesSequence .from_df (
545+ df ,
546+ time_col = "date" ,
547+ target_col = "value" ,
548+ train_length = 10 ,
549+ predict_length = 5 ,
550+ stride = 1 ,
551+ )
552+ self .assertLess (len (seq .sequences ), len (seq_stride1 .sequences ))
0 commit comments