iita-python 1.2.1__tar.gz → 1.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iita_python
3
- Version: 1.2.1
3
+ Version: 1.4
4
4
  Summary: IITA algorithm in python
5
5
  Author-email: Aliaksei Badnarchuk <alexejbodnarchuk@gmail.com>
6
6
  Requires-Python: >=3.9
@@ -0,0 +1,5 @@
1
+ from .dataset import Dataset
2
+ from .quasiorder import ind_gen
3
+ from . import fit_metrics
4
+
5
+ __all__ = ['Dataset', 'ind_gen', 'fit_metrics']
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '1.4'
22
+ __version_tuple__ = version_tuple = (1, 4)
23
+
24
+ __commit_id__ = commit_id = 'g8439da544'
@@ -15,12 +15,12 @@ def pairwise_diff_ce(rp: pd.DataFrame) -> pd.DataFrame:
15
15
  items = rp.shape[1]
16
16
  subjects = rp.shape[0]
17
17
 
18
- ce = pd.DataFrame(0, index=np.arange(items), columns=np.arange(items))
18
+ ce = pd.DataFrame(0, index=rp.columns, columns=rp.columns)
19
19
  for i in range(subjects):
20
20
  # for subject i, if a < b, add b - a for all item pairs (a,b)
21
21
  # this is equivalent to ce[a][b] += 1 if a=0 and b=1, but works for non-binary data as well
22
22
 
23
- row = rp.loc[i].to_numpy()
23
+ row = rp.iloc[i].to_numpy()
24
24
  ce -= np.clip(row[:, None] - row[None, :], None, 0)
25
25
 
26
26
  return ce
@@ -39,10 +39,10 @@ def missing_value_substitution_ce(rp: pd.DataFrame) -> pd.DataFrame:
39
39
 
40
40
  for i in range(items):
41
41
  # substitute missing values in item i with the mean of the item
42
- col = rp1.loc[:, i].to_numpy()
42
+ col = rp1.iloc[:, i].to_numpy()
43
43
  mean_val = np.nanmean(col)
44
44
  col = pd.Series(col).fillna(mean_val)
45
- rp1.loc[:, i] = col
45
+ rp1.iloc[:, i] = col
46
46
 
47
47
  # then calculate pairwise difference counterexamples
48
48
  return pairwise_diff_ce(rp1)
@@ -64,10 +64,10 @@ def relativify(calculator: callable):
64
64
  items = rp.shape[1]
65
65
  subjects = rp.shape[0]
66
66
 
67
- valid_cases = pd.DataFrame(0, index=np.arange(items), columns=np.arange(items))
67
+ valid_cases = pd.DataFrame(0, index=rp.columns, columns=rp.columns)
68
68
  for i in range(subjects):
69
69
  #for subject i, increment all cases where neither a nor b are NaN (valid case for counterexamples)
70
- not_nan = np.logical_not(rp.loc[i].isna())
70
+ not_nan = np.logical_not(rp.iloc[i].isna())
71
71
  valid_cases += np.outer(not_nan, not_nan).astype(int)
72
72
 
73
73
  # avoid division by zero
@@ -0,0 +1,91 @@
1
+ import numpy as np
2
+ import numpy.typing as npt
3
+ from typing import Self, List
4
+ import pandas as pd
5
+
6
+ class Dataset():
7
+ # full name aliases for response patterns, counterexamples and equivalence examples
8
+ @property
9
+ def response_patterns(self) -> pd.DataFrame:
10
+ return self.rp
11
+ @response_patterns.setter
12
+ def response_patterns(self, inp: pd.DataFrame) -> None:
13
+ self.rp = inp
14
+
15
+ @property
16
+ def counterexamples(self) -> pd.DataFrame:
17
+ return self.ce
18
+ @counterexamples.setter
19
+ def counterexamples(self, inp: pd.DataFrame) -> None:
20
+ self.ce = inp
21
+
22
+ @property
23
+ def equiv_examples(self) -> pd.DataFrame:
24
+ return self.eqe
25
+ @equiv_examples.setter
26
+ def equiv_examples(self, inp: pd.DataFrame) -> None:
27
+ self.eqe = inp
28
+
29
+ @property
30
+ def items(self):
31
+ return self.rp.shape[1]
32
+
33
+ @property
34
+ def subjects(self):
35
+ return self.rp.shape[0]
36
+
37
+ @property
38
+ def filled_vals(self):
39
+ return (np.logical_not(np.isnan(self.rp)).astype(int)).sum(axis=0)
40
+
41
+ def __init__(self, response_patterns: pd.DataFrame | npt.NDArray | List[List[int]]):
42
+ """
43
+ Computes counterexamples, equivalence examples and valid CE cases from response patterns\n
44
+ Supports pandas dataframes, numpy arrays, and python lists\n
45
+ Rows represent the subjects, columns - the items\n
46
+ """
47
+ self.rp = pd.DataFrame(response_patterns)
48
+ self.ce = None
49
+ self.eqe = None
50
+
51
+ rp_numpy = self.rp.to_numpy()
52
+
53
+ # setting missing values (NaN) to 0
54
+ rp_no_nan = np.nan_to_num(rp_numpy, 0) # NaN to 0
55
+ not_rp_no_nan = np.logical_not(np.nan_to_num(rp_numpy, 1)).astype(int) # NaN to 1, negated to 0
56
+
57
+ # counterexamples computation
58
+ # all cases where a=0 and b=1 (counterexamples to b->a or a <= b)
59
+ self.ce = pd.DataFrame(not_rp_no_nan.T @ rp_no_nan, index=self.rp.columns, columns=self.rp.columns)
60
+
61
+ # equivalence examples computation
62
+ # all cases where a=b, equivalent to ((a and b) or (~a and ~b))
63
+ a_and_b = rp_no_nan.T @ rp_no_nan
64
+ not_a_and_not_b = (not_rp_no_nan).T @ (not_rp_no_nan)
65
+ self.eqe = pd.DataFrame(a_and_b + not_a_and_not_b, index=self.rp.columns, columns=self.rp.columns)
66
+
67
+ # valid CE cases computation
68
+ rp_isnt_nan = np.logical_not(np.isnan(rp_numpy)).astype(int)
69
+ self.valid_ce_cases = pd.DataFrame(rp_isnt_nan.T @ rp_isnt_nan, index=self.rp.columns, columns=self.rp.columns)
70
+
71
+ def add(self, dataset_to_add: Self):
72
+ """
73
+ Add a second IITA_Dataset: concatenate the response patterns, add CE, EQE and valid CE cases\n
74
+ Item amounts must match, else ValueError
75
+ """
76
+ if (self.items != dataset_to_add.items):
77
+ raise ValueError('Item amounts must match')
78
+
79
+ self.rp = pd.concat(self.rp, dataset_to_add.rp)
80
+ self.ce = self.ce + dataset_to_add.ce
81
+ self.eqe = self.eqe + dataset_to_add.eqe
82
+ self.valid_ce_cases = self.valid_ce_cases + dataset_to_add.valid_ce_cases
83
+
84
+ @property
85
+ def relative_ce(self) -> pd.DataFrame:
86
+ """
87
+ Returns the counterexamples matrix accounting for missing values
88
+ """
89
+ return self.ce / self.valid_ce_cases
90
+
91
+ __iadd__ = add
@@ -20,31 +20,20 @@ class QuasiOrder:
20
20
  if (self.full_matrix[i][j]):
21
21
  edge_list.append([i+buff, j+buff])
22
22
 
23
- return edge_list
23
+ return edge_list
24
24
 
25
- def unfold_examples(
26
- matrix: pd.DataFrame
27
- ) -> npt.NDArray:
25
+ def ind_gen(counterexamples: pd.DataFrame, n: int) -> list[QuasiOrder]:
28
26
  """
29
- Turns an item/item metric DataFrame into
30
- a list of tuples of the form (x, [i, j]), where matrix[i, j] = x.\n
27
+ Inductively generates quasiorders from counterexample count DataFrame\n
31
28
  """
32
29
 
33
- dfmatrix = pd.DataFrame(matrix)
30
+ dfce = pd.DataFrame(counterexamples)
34
31
 
35
- n = dfmatrix.shape[0]
32
+ n = dfce.shape[0]
36
33
  pos = np.arange(n, dtype=np.int_)
37
34
  i = np.repeat(pos, n)
38
35
  j = np.tile(pos, n)
39
- res = np.array(list(zip(dfmatrix.to_numpy()[i, j], i, j)))
40
- return res[res[:, 1] != res[:, 2]]
41
-
42
- def ind_gen(counterexamples: npt.NDArray, n: int) -> list[QuasiOrder]:
43
- """
44
- Inductively generates quasiorders from counterexample edge list\n
45
- Counterexamples is expected to be of the form returned by unfold_examples (array of (x, i, j) tuples)\n
46
- """
47
- ce = counterexamples
36
+ ce = np.array(list(zip(dfce.to_numpy()[i, j], i, j)))
48
37
 
49
38
  if (len(ce) == 0): raise ValueError("Counterexamples can't be empty")
50
39
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iita_python
3
- Version: 1.2.1
3
+ Version: 1.4
4
4
  Summary: IITA algorithm in python
5
5
  Author-email: Aliaksei Badnarchuk <alexejbodnarchuk@gmail.com>
6
6
  Requires-Python: >=3.9
@@ -1,4 +0,0 @@
1
- from .dataset import Dataset
2
- from .quasiorder import ind_gen, unfold_examples
3
-
4
- __all__ = ['Dataset', 'unfold_examples', 'ind_gen']
@@ -1,34 +0,0 @@
1
- # file generated by setuptools-scm
2
- # don't change, don't track in version control
3
-
4
- __all__ = [
5
- "__version__",
6
- "__version_tuple__",
7
- "version",
8
- "version_tuple",
9
- "__commit_id__",
10
- "commit_id",
11
- ]
12
-
13
- TYPE_CHECKING = False
14
- if TYPE_CHECKING:
15
- from typing import Tuple
16
- from typing import Union
17
-
18
- VERSION_TUPLE = Tuple[Union[int, str], ...]
19
- COMMIT_ID = Union[str, None]
20
- else:
21
- VERSION_TUPLE = object
22
- COMMIT_ID = object
23
-
24
- version: str
25
- __version__: str
26
- __version_tuple__: VERSION_TUPLE
27
- version_tuple: VERSION_TUPLE
28
- commit_id: COMMIT_ID
29
- __commit_id__: COMMIT_ID
30
-
31
- __version__ = version = '1.2.1'
32
- __version_tuple__ = version_tuple = (1, 2, 1)
33
-
34
- __commit_id__ = commit_id = 'gda19693c6'
@@ -1,95 +0,0 @@
1
- import numpy as np
2
- import numpy.typing as npt
3
- from typing import Self, List
4
- import pandas as pd
5
-
6
- class Dataset():
7
- #aliases for response_patterns, counterexamples, equiv_examples
8
- @property
9
- def rp(self) -> pd.DataFrame:
10
- return self._rp
11
- @rp.setter
12
- def rp(self, inp: pd.DataFrame) -> None:
13
- self._rp = inp
14
- response_patterns = rp
15
-
16
- @property
17
- def ce(self) -> pd.DataFrame:
18
- return self._ce
19
- @ce.setter
20
- def ce(self, inp: pd.DataFrame) -> None:
21
- self._ce = inp
22
- counterexamples = ce
23
-
24
- @property
25
- def eqe(self) -> pd.DataFrame:
26
- return self._eqe
27
- @eqe.setter
28
- def eqe(self, inp: pd.DataFrame) -> None:
29
- self._eqe = inp
30
- equiv_examples = eqe
31
-
32
- @property
33
- def items(self):
34
- return self.rp.shape[1]
35
-
36
- @property
37
- def subjects(self):
38
- return self.rp.shape[0]
39
-
40
- @property
41
- def filled_vals(self):
42
- return (~np.isnan(self.rp)).sum(axis=0)
43
-
44
- def __init__(self, response_patterns: pd.DataFrame | npt.NDArray | List[List[int]]):
45
- """
46
- Computes the counterexamples and equivalence examples from response patterns\n
47
- Supports pandas dataframes, numpy arrays, and python lists\n
48
- Rows represent the subjects, columns - the items\n
49
- """
50
- self._rp = pd.DataFrame(response_patterns, index=None, columns=None)
51
- self._ce = None
52
- self._eqe = None
53
-
54
- #counterexamples computation
55
- self.ce = pd.DataFrame(0, index=np.arange(self.items), columns=np.arange(self.items))
56
-
57
- for i in range(self.subjects):
58
- #for subject i, increment all cases where a=0 and b=1 (counterexamples to b->a or a <= b)
59
- not_a = (self.rp.loc[i] == 0)
60
- b = (self.rp.loc[i] == 1)
61
- self.ce.loc[not_a, b] += 1
62
-
63
- #equivalence examples computation
64
- self.eqe = pd.DataFrame(0, index=np.arange(self.items), columns=np.arange(self.items))
65
- for i in range(self.subjects):
66
- #for subject i, increment all cases where a=b (examples of equivalence of a and b)
67
- row = self.rp.loc[i].to_numpy()
68
- self.eqe += np.equal.outer(row, row).astype(int)
69
-
70
- self.valid_ce_cases = pd.DataFrame(0, index=np.arange(self.items), columns=np.arange(self.items))
71
- for i in range(self.subjects):
72
- #for subject i, increment all cases where neither a nor b are NaN (valid case for counterexamples)
73
- not_nan = np.logical_not(self.rp.loc[i].isna())
74
- self.valid_ce_cases += np.outer(not_nan, not_nan).astype(int)
75
-
76
- def add(self, dataset_to_add: Self):
77
- """
78
- Add a second IITA_Dataset: concatenate the response patterns, add counterexamples and equivalence examples\n
79
- Item amounts must match, else ValueError
80
- """
81
- if (self.items != dataset_to_add.items):
82
- raise ValueError('Item amounts must match')
83
-
84
- self.rp = pd.concat(self.rp, dataset_to_add.rp)
85
- self.ce = self.ce + dataset_to_add.ce
86
- self.eqe = self.eqe + dataset_to_add.eqe
87
-
88
- @property
89
- def relative_ce(self) -> pd.DataFrame:
90
- """
91
- Returns the counterexamples matrix accounting for missing values
92
- """
93
- return self.ce / self.valid_ce_cases
94
-
95
- __iadd__ = add
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes