From afdff582ff0cf59cf00548462f3c800be8b7e553 Mon Sep 17 00:00:00 2001 From: Alexander James Date: Wed, 19 Jun 2024 10:35:13 -0700 Subject: [PATCH 1/4] create dropna_matrix --- pyleoclim/utils/tsbase.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/pyleoclim/utils/tsbase.py b/pyleoclim/utils/tsbase.py index 111e5d13..a88e2429 100644 --- a/pyleoclim/utils/tsbase.py +++ b/pyleoclim/utils/tsbase.py @@ -384,6 +384,36 @@ def dropna(ys, ts, verbose=False): return ys, ts +def dropna_matrix(matrix, verbose=False): + '''Drop NaN values from matrix + + Remove columns from matrix that contain nans + + Parameters + ---------- + matrix : array + A matrix, NaNs allowed + verbose : bool + If True, will print a warning message + + Returns + ------- + matrix : array + The matrix without nans + + See Also + -------- + + https://pandas.pydata.org/docs/reference/api/pandas.Series.dropna.html + + ''' + matrix = matrix[:, ~np.isnan(matrix).any(axis=0)] + + if verbose and any(np.isnan(matrix)): + print('NaNs have been detected and dropped.') + + return matrix + def sort_ts(ys, ts, ascending = True, verbose=False): ''' Sort timeseries From 2558572eb7c6cee7ff447fd1fd061baa38ade4b7 Mon Sep 17 00:00:00 2001 From: Alexander James Date: Wed, 19 Jun 2024 10:35:24 -0700 Subject: [PATCH 2/4] add dropna option to geoseries --- pyleoclim/core/geoseries.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/pyleoclim/core/geoseries.py b/pyleoclim/core/geoseries.py index c4485e25..c62aded9 100644 --- a/pyleoclim/core/geoseries.py +++ b/pyleoclim/core/geoseries.py @@ -8,6 +8,7 @@ import matplotlib.pyplot as plt import re import pandas as pd +import numpy as np #from copy import deepcopy from matplotlib import gridspec @@ -166,7 +167,17 @@ def __init__(self, time, value, lat, lon, elevation = None, time_unit=None, time time_name='Time' else: pass - + + if dropna: + if depth is not None: + matrix = np.array([time,value,depth]) + matrix = tsbase.dropna_matrix(matrix) + time = matrix[0,:] + value = matrix[1,:] + depth = matrix[2,:] + else: + pass + # assign latitude if lat is not None: lat = float(lat) From 95f86f3bc433b51aab3591be988c7a0463127813 Mon Sep 17 00:00:00 2001 From: Alexander James Date: Wed, 19 Jun 2024 10:35:31 -0700 Subject: [PATCH 3/4] include tests for dropna for geoseries --- pyleoclim/tests/test_core_GeoSeries.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/pyleoclim/tests/test_core_GeoSeries.py b/pyleoclim/tests/test_core_GeoSeries.py index 281c61f1..7b90e2ec 100644 --- a/pyleoclim/tests/test_core_GeoSeries.py +++ b/pyleoclim/tests/test_core_GeoSeries.py @@ -45,6 +45,31 @@ def multiple_pinkgeoseries(nrecs = 20, seed = 108, geobox=[-85.0,85.0,-180,180]) return pyleo.MultipleGeoSeries(ts_list, label='Multiple Pink GeoSeries') +class TestUIGeoSeriesInit: + ''' Test for GeoSeries instantiation ''' + + def test_init_no_dropna(self, evenly_spaced_series): + ts = evenly_spaced_series + t = ts.time + v = ts.value + d = np.arange(len(t)) + v[0] = np.nan + ts2 = pyleo.GeoSeries(time=t,value=v,depth=d,dropna=False, verbose=False,lat=0,lon=0) + assert np.isnan(ts2.value[0]) + assert ts2.depth[0] == d[0] + + def test_init_dropna(self, evenly_spaced_series): + ts = evenly_spaced_series + t = ts.time + v = ts.value + d = np.arange(len(t)) + v[0] = np.nan + ts2 = pyleo.GeoSeries(time=t,value=v,depth=d,dropna=True, verbose=False,lat=0,lon=0) + print(ts2.value) + assert ~np.isnan(ts2.value[0]) + assert ts2.depth[0] == d[1] + + class TestUIGeoSeriesResample(): ''' test GeoSeries.Resample() ''' From 4d73e942d4dd59a464fd01c83b4a87690eaa2195 Mon Sep 17 00:00:00 2001 From: Alexander James Date: Wed, 19 Jun 2024 10:54:41 -0700 Subject: [PATCH 4/4] couple more tests --- pyleoclim/tests/test_core_GeoSeries.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/pyleoclim/tests/test_core_GeoSeries.py b/pyleoclim/tests/test_core_GeoSeries.py index 7b90e2ec..b6521143 100644 --- a/pyleoclim/tests/test_core_GeoSeries.py +++ b/pyleoclim/tests/test_core_GeoSeries.py @@ -48,7 +48,7 @@ def multiple_pinkgeoseries(nrecs = 20, seed = 108, geobox=[-85.0,85.0,-180,180]) class TestUIGeoSeriesInit: ''' Test for GeoSeries instantiation ''' - def test_init_no_dropna(self, evenly_spaced_series): + def test_init_no_dropna_depth(self, evenly_spaced_series): ts = evenly_spaced_series t = ts.time v = ts.value @@ -58,7 +58,7 @@ def test_init_no_dropna(self, evenly_spaced_series): assert np.isnan(ts2.value[0]) assert ts2.depth[0] == d[0] - def test_init_dropna(self, evenly_spaced_series): + def test_init_dropna_depth(self, evenly_spaced_series): ts = evenly_spaced_series t = ts.time v = ts.value @@ -69,6 +69,23 @@ def test_init_dropna(self, evenly_spaced_series): assert ~np.isnan(ts2.value[0]) assert ts2.depth[0] == d[1] + def test_init_no_dropna(self, evenly_spaced_series): + ts = evenly_spaced_series + t = ts.time + v = ts.value + v[0] = np.nan + ts2 = pyleo.GeoSeries(time=t,value=v,dropna=False, verbose=False,lat=0,lon=0) + assert np.isnan(ts2.value[0]) + + def test_init_dropna(self, evenly_spaced_series): + ts = evenly_spaced_series + t = ts.time + v = ts.value + v[0] = np.nan + ts2 = pyleo.GeoSeries(time=t,value=v,dropna=True, verbose=False,lat=0,lon=0) + print(ts2.value) + assert ~np.isnan(ts2.value[0]) + class TestUIGeoSeriesResample(): ''' test GeoSeries.Resample()