Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions nzpyida/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import datetime
import warnings
from copy import deepcopy
from typing import Optional, Dict

from collections import OrderedDict

Expand Down Expand Up @@ -1849,13 +1850,15 @@ def _drop(self, objectname, object_type = "T"):

if object_type == "T":
to_drop = "TABLE"
if_exists = "IF EXISTS"
elif object_type == "V":
to_drop = "VIEW"
if_exists = ''
else:
raise ValueError("Unknown type to drop")

try:
self._prepare_and_execute("DROP %s %s"%(to_drop,objectname))
self._prepare_and_execute("DROP %s %s %s"%(to_drop,objectname,if_exists))
except Exception as e:
if self._con_type == "odbc":
if e.value[0] == "42S02":
Expand Down Expand Up @@ -2054,6 +2057,7 @@ def _create_table(self, dataframe, tablename, primary_key=None):

column_string = ''
for column in dataframe.columns:
# print(f"THe current column is {column} and type : {type(dataframe.dtypes[column])} and bool :")
if dataframe.dtypes[column] in [object,bool]:
# Handle boolean type
if set(dataframe[column].unique()).issubset([True, False, 0, 1, np.nan]):
Expand All @@ -2063,10 +2067,11 @@ def _create_table(self, dataframe, tablename, primary_key=None):
column_string += "\"%s\" VARCHAR(255) NOT NULL, PRIMARY KEY (\"%s\")," % (str(column).strip(), str(column).strip())
else:
column_string += "\"%s\" VARCHAR(255)," % str(column).strip()
elif dataframe.dtypes[column] == np.dtype('datetime64[ns]'):
# This is a first patch for handling dates
# TODO: Dates as timestamp in the database
elif dataframe.dtypes[column] in ["str"]:
column_string += "\"%s\" VARCHAR(255)," % str(column).strip()
elif pd.api.types.is_datetime64_any_dtype(dataframe.dtypes[column]):
print(f" Detected datetime column: {column} (type: {dataframe.dtypes[column]})")
column_string += "\"%s\" TIMESTAMP," % str(column).strip()
else:
if dataframe.dtypes[column] in [np.int64, int, np.int8, np.int32]:
if abs(dataframe[column].max()) < 2147483647/2: # might get bigger
Expand Down
30 changes: 25 additions & 5 deletions nzpyida/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -603,11 +603,25 @@ def __enter__(self):
"""
return self

def __exit__(self):
def __exit__(self, exc_type, exc_val, exc_tb):
"""
Allow the object to be used with a "with" statement. Make sure that
allow possible views related to the IdaDataFrame with be deleted when
allow possible views related to the IdaDataFrame will be deleted when
the object goes out of scope

Parameters
----------
exc_type : type
The type of exception that occurred (None if no exception)
exc_val : Exception
The exception instance (None if no exception)
exc_tb : traceback
The traceback object (None if no exception)

Returns
-------
bool or None
Return False to propagate exceptions, True to suppress them
"""
while self.internal_state.viewstack:
try :
Expand All @@ -616,7 +630,9 @@ def __exit__(self):
if view != self.tablename:
drop = "DROP VIEW \"%s\"" %view
self._prepare_and_execute(drop, autocommit = True)
except: pass
except:
pass
return False

#We decided not to allow columns access idadf.columnname like this for now.
#We could decide to allow it but for this we may have to switch all
Expand Down Expand Up @@ -1687,7 +1703,7 @@ def cov(self):

@timed
@idadf_state
def corr(self, method="pearson", features=None, ignore_indexer=True):
def corr(self, method="pearson", features=None, ignore_indexer=True, min_periods=1):
"""
Compute the correlation matrix, composed of correlation coefficients
between all pairs of columns in self.
Expand All @@ -1700,6 +1716,10 @@ def corr(self, method="pearson", features=None, ignore_indexer=True):
the pearson correlation coefficient. The Spearman rank correlation
is also available. Admissible values are: "pearson", "spearman".

min_periods : int, optional
Minimum number of observations required per pair of columns to have a valid result.
Currently only available for Pearson and Spearman correlation.

Returns
-------
correlation matrix: DataFrame
Expand All @@ -1717,7 +1737,7 @@ def corr(self, method="pearson", features=None, ignore_indexer=True):
"""
from nzpyida.statistics import corr
#return corr(idadf=self, features=features, ignore_indexer=ignore_indexer)
return corr(idadf=self)
return corr(idadf=self, min_periods=min_periods)

@timed

Expand Down
8 changes: 4 additions & 4 deletions nzpyida/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ def org_columns_names(self):
def min(self):
result = super(IdaSeries, self).min()
#import pdb; pdb.set_trace()
return result[0]
return result.iloc[0]

def max(self):
result = super(IdaSeries, self).max()
#import pdb; pdb.set_trace()
return result[0]
return result.iloc[0]

def _clone(self):
"""
Expand All @@ -78,4 +78,4 @@ def _clone(self):
newida.internal_state._cumulative = deepcopy(self.internal_state._cumulative)
newida.internal_state.order = deepcopy(self.internal_state.order)
newida._org_columns_names = self._org_columns_names
return newida
return newida
97 changes: 46 additions & 51 deletions nzpyida/statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ def pivot_table(idadf, values=None, columns=None, max_entries=1000, sort=None,
dataframe = catdataframe.join(dataframe[agg_values].stack().reset_index(1))
dataframe['level_1'] = pd.Categorical(dataframe['level_1'], agg_values)
dataframe = dataframe.rename(columns={'level_1': None})
dataframe = dataframe.sort([None] + categorical_columns)
dataframe = dataframe.sort_values(by=[None] + categorical_columns)

dataframe.set_index([None] + categorical_columns, inplace=True)
dataframe = dataframe.astype(float)
Expand Down Expand Up @@ -650,7 +650,7 @@ def quantile(idadf, q=0.5):
result = result.astype('float')

if len(result) == 1:
result = result[0]
result = result.iloc[0]

return result

Expand Down Expand Up @@ -768,50 +768,45 @@ def cov_old(idadf, other=None):

return result


def corr(idadf):
if not idadf._idadb._is_netezza_system():
return corr_old(idadf)
def corr(idadf, min_periods):
import pandas as pd
import numpy as np

numerical_columns = idadf._get_numerical_columns()
if len(numerical_columns) < 2:
print(idadf.name + " has less than two numeric columns")
return
column_string = ""
for column in numerical_columns:
column_string += "\"" + column + "\";"

result_df = pd.DataFrame(columns=numerical_columns, index=numerical_columns)

# print(result_df)

table_name = idadf.internal_state.current_state
outtable = idadf._idadb._get_valid_tablename(prefix="corr_")

idadf._idadb._call_stored_procedure("CORRELATION1000MATRIX ",
intable=table_name,
incolumn=column_string,
outtable=outtable)

# the calls of substring remove the surrounding double quotes
result_query = ("SELECT substring(VARXNAME,2,length(VARXNAME)-2) as VARXNAME, " +
"substring(VARYNAME,2,length(VARYNAME)-2) as VARYNAME, " +
"CORRELATION " +
"FROM " + outtable + " ORDER BY varxname, varyname;")

corr_df = idadf.ida_query(result_query)

for index in corr_df.index.values:

col_list = []
for column in corr_df.columns.values:
col_list.append(corr_df.at[index, column])

result_df.at[col_list[0], col_list[1]] = col_list[2]

for column in result_df.columns:
result_df[column] = result_df[column].astype(float)
value = idadf._idadb.drop_table(outtable)
if len(numerical_columns) < 2:
raise ValueError("Need at least 2 numerical columns for correlation")

table_name = idadf._name

# Initialize result matrix
result_df = pd.DataFrame(
index=numerical_columns,
columns=numerical_columns,
dtype=float
)

for i, col1 in enumerate(numerical_columns):
select_parts = []
for col2 in numerical_columns:
select_parts.append(f'CORR("{col1}", "{col2}") as "{col2}"')
query = f"""
SELECT {', '.join(select_parts)}
FROM {table_name}
"""
try:
result = idadf._idadb.ida_query(query, first_row_only=True)
if result is not None and len(result) > 0:
for j, col2 in enumerate(numerical_columns):
corr_value = result[j]
result_df.at[col1, col2] = corr_value
else:
for col2 in numerical_columns:
result_df.at[col1, col2] = np.nan
except Exception as e:
print(f"Error calculating correlations for {col1}: {e}")
for col2 in numerical_columns:
result_df.at[col1, col2] = np.nan
return result_df


Expand Down Expand Up @@ -963,7 +958,7 @@ def mad(idadf):
result = result.astype('float')

if isinstance(idadf, nzpyida.IdaSeries):
result = result[0]
result = result.iloc[0]

return result

Expand Down Expand Up @@ -1016,7 +1011,7 @@ def count(idadf):
result = result.astype(int)

if isinstance(idadf, nzpyida.IdaSeries):
result = result[0]
result = result.iloc[0]

return result

Expand All @@ -1030,7 +1025,7 @@ def count_distinct(idadf):
result = result.astype(int)

if isinstance(idadf, nzpyida.IdaSeries):
result = result[0]
result = result.iloc[0]

return result

Expand All @@ -1050,7 +1045,7 @@ def std(idadf):
result.index = columns

if isinstance(idadf, nzpyida.IdaSeries):
result = result[0]
result = result.iloc[0]

return result

Expand All @@ -1070,7 +1065,7 @@ def var(idadf):
result.index = columns

if isinstance(idadf, nzpyida.IdaSeries):
result = result[0]
result = result.iloc[0]

return result

Expand All @@ -1090,7 +1085,7 @@ def mean(idadf):
result.index = columns

if isinstance(idadf, nzpyida.IdaSeries):
result = result[0]
result = result.iloc[0]

return result

Expand All @@ -1111,7 +1106,7 @@ def ida_sum(idadf):
result.index = columns

if isinstance(idadf, nzpyida.IdaSeries):
result = result[0]
result = result.iloc[0]

return result

Expand All @@ -1132,6 +1127,6 @@ def median(idadf):
result.index = columns

if isinstance(idadf, nzpyida.IdaSeries):
result = result[0]
result = result.iloc[0]

return result
8 changes: 2 additions & 6 deletions nzpyida/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@

py.test --dsn=<DSN>
Do the test routine with the data source <DSN> as defined in ODBC settings.
For nzpy connection provide the dbname in dsn

py.test --dsn=<DSN> --uid=<UID> --pwd=<pwd>
In case userID and password are not stored in ODBC settings.
Expand Down Expand Up @@ -431,12 +432,7 @@ def session_teardown(idadb, idadf, idaview, request):
Defines cleanup actions to be done once the testing procedure is done.
"""
def fin():
try:
idadb.drop_table(idadf.name)
idadb.drop_view(idaview.name)
idadb.commit()
idadb.close()
except: pass
pass
request.addfinalizer(fin)
return

Expand Down
1 change: 1 addition & 0 deletions nzpyida/tests/test_base_connexion.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ def test_idadb_rollback(self, idadb, df):
idadb.commit()
assert(idadb.exists_table("TEST_ROLLBACK_59673030586849305074") == 0)

@pytest.mark.skip()
def test_idadb_close(self, idadb_tmp):
idadb_tmp.close()
with pytest.raises(IdaDataBaseError):
Expand Down
4 changes: 0 additions & 4 deletions nzpyida/tests/test_base_table_manipulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ def test_idadb_drop_table(self, idadb, idadf_tmp):
idadb.drop_table(idadf_tmp.name)
assert(idadb.exists_table(idadf_tmp.name) == 0)

def test_idadb_drop_table_value_error(self, idadb):
with pytest.raises(ValueError):
idadb.drop_table("NOTEXISTINGOBJECT_496070383095079384063739509")

@pytest.mark.skipif("'netezza' in config.getvalue('jdbc') or config.getvalue('hostname') != ''")
def test_idadb_drop_table_type_error(self, idadb, idaview):
with pytest.raises(TypeError):
Expand Down
Loading