Skip to content

interaction_matrix

logger = logging.getLogger(__name__) module-attribute

InteractionMatrix

Bases: SelectionIDMixin, SelectionTimestampMixin

Matrix of interaction data between users and items.

It provides a number of properties and methods for easy manipulation of this interaction data.

.. attention::

- The InteractionMatrix does not assume binary user-item pairs.
  If a user interacts with an item more than once, there will be two
  entries for this user-item pair.

- We assume that the user and item IDs are integers starting from 0. IDs
  that are indicated by "-1" are reserved to label the user or item to
  be predicted. This assumption is crucial as it will be used during the
  split scheme and evaluation of the RS since it will affect the 2D shape
  of the CSR matrix
Source code in src/recnexteval/matrix/interaction_matrix.py
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
class InteractionMatrix(SelectionIDMixin, SelectionTimestampMixin):
    """Matrix of interaction data between users and items.

    It provides a number of properties and methods for easy manipulation of this interaction data.

    .. attention::

        - The InteractionMatrix does not assume binary user-item pairs.
          If a user interacts with an item more than once, there will be two
          entries for this user-item pair.

        - We assume that the user and item IDs are integers starting from 0. IDs
          that are indicated by "-1" are reserved to label the user or item to
          be predicted. This assumption is crucial as it will be used during the
          split scheme and evaluation of the RS since it will affect the 2D shape
          of the CSR matrix
    """

    ITEM_IX = "iid"
    USER_IX = "uid"
    TIMESTAMP_IX = "ts"
    INTERACTION_IX = "interactionid"
    MASKED_LABEL = -1

    def __init__(
        self,
        df: pd.DataFrame,
        item_ix: str,
        user_ix: str,
        timestamp_ix: str,
        shape: None | tuple[int, int] = None,
        skip_df_processing: bool = False,
    ) -> None:
        self.user_item_shape: tuple[int, int]
        """The shape of the interaction matrix, i.e. `|user| x |item|`."""
        if shape:
            self.user_item_shape = shape

        if skip_df_processing:
            self._df = df
            return

        col_mapper = {
            item_ix: self.ITEM_IX,
            user_ix: self.USER_IX,
            timestamp_ix: self.TIMESTAMP_IX,
        }
        df = df.rename(columns=col_mapper)
        required_columns = [
            self.USER_IX,
            self.ITEM_IX,
            self.TIMESTAMP_IX,
        ]
        extra_columns = [col for col in df.columns if col not in required_columns]
        df = df[required_columns + extra_columns].copy()
        # TODO refactor this statement below
        df = df.reset_index(drop=True).reset_index().rename(columns={"index": InteractionMatrix.INTERACTION_IX})

        self._df = df

    def copy(self) -> Self:
        """Create a deep copy of this InteractionMatrix."""
        return deepcopy(self)

    def copy_df(self, reset_index: bool = False) -> "pd.DataFrame":
        """Create a deep copy of the dataframe."""
        if reset_index:
            return deepcopy(self._df.reset_index(drop=True))
        return deepcopy(self._df)

    def concat(self, im: "InteractionMatrix | pd.DataFrame") -> Self:
        """Concatenate this InteractionMatrix with another.

        Note:
            This is a inplace operation. and will modify the current object.
        """
        if isinstance(im, pd.DataFrame):
            self._df = pd.concat([self._df, im])
        else:
            self._df = pd.concat([self._df, im._df])

        return self

    # TODO this should be shifted to prediction matrix
    def union(self, im: "InteractionMatrix") -> Self:
        """Combine events from this InteractionMatrix with another."""
        return self + im

    def difference(self, im: "InteractionMatrix") -> Self:
        """Difference between this InteractionMatrix and another."""
        return self - im

    @property
    def values(self) -> csr_matrix:
        """All user-item interactions as a sparse matrix of size (|users|, |items|).

        The shape of the matrix is determined by the `user_item_shape` attribute. Each row represents
        a user and each column represents an item. The index of the rows and columns correspond to the user
        and item IDs respectively. An entry in the matrix is 1 if there is an interaction.
        """
        # TODO issue with -1 labeling in the interaction matrix should i create prediction matrix
        if not hasattr(self, "user_item_shape"):
            raise AttributeError(
                "InteractionMatrix has no `user_item_shape` attribute. Please call mask_shape() first."
            )

        values = np.ones(self._df.shape[0])
        indices = self._df[[self.USER_IX, self.ITEM_IX]].values
        indices = (indices[:, 0], indices[:, 1])

        matrix = csr_matrix((values, indices), shape=self.user_item_shape, dtype=np.int32)
        return matrix

    @property
    def indices(self) -> tuple[list[int], list[int]]:
        """Returns a tuple of lists of user IDs and item IDs corresponding to interactions.

        :return: tuple of lists of user IDs and item IDs that correspond to at least one interaction.
        :rtype: tuple[list[int], list[int]]
        """
        return self.values.nonzero()

    def nonzero(self) -> tuple[list[int], list[int]]:
        return self.values.nonzero()

    @overload
    def _apply_mask(self, mask: pd.Series) -> Self: ...
    @overload
    def _apply_mask(self, mask: pd.Series, inplace: Literal[True]) -> None: ...
    @overload
    def _apply_mask(self, mask: pd.Series, inplace: Literal[False]) -> Self: ...
    def _apply_mask(self, mask: pd.Series, inplace: bool = False) -> None | Self:
        interaction_m = self if inplace else self.copy()
        interaction_m._df = interaction_m._df[mask]
        return None if inplace else interaction_m

    # Timestamp selection helpers moved to SelectionTimestampMixin (src/recnexteval/matrix/filters.py)

    def __add__(self, im: "InteractionMatrix") -> Self:
        """Combine events from this InteractionMatrix with another.

        :param im: InteractionMatrix to union with.
        :type im: InteractionMatrix
        :return: Union of interactions in this InteractionMatrix and the other.
        :rtype: InteractionMatrix
        """
        df = pd.concat([self._df, im._df], copy=False)

        shape = None
        if hasattr(self, "user_item_shape") and hasattr(im, "user_item_shape"):
            shape = (
                max(self.user_item_shape[0], im.user_item_shape[0]),
                max(self.user_item_shape[1], im.user_item_shape[1]),
            )
            self.user_item_shape = shape

        return type(self)(
            df,
            InteractionMatrix.ITEM_IX,
            InteractionMatrix.USER_IX,
            InteractionMatrix.TIMESTAMP_IX,
            shape,
            True,
        )

    def __sub__(self, im: "InteractionMatrix") -> Self:
        full_data = pd.MultiIndex.from_frame(self._df)
        data_part_2 = pd.MultiIndex.from_frame(im._df)
        data_part_1 = full_data.difference(data_part_2).to_frame().reset_index(drop=True)

        shape = None
        if hasattr(self, "user_item_shape") and hasattr(im, "user_item_shape"):
            shape = (
                max(self.user_item_shape[0], im.user_item_shape[0]),
                max(self.user_item_shape[1], im.user_item_shape[1]),
            )

        return type(self)(
            data_part_1,
            InteractionMatrix.ITEM_IX,
            InteractionMatrix.USER_IX,
            InteractionMatrix.TIMESTAMP_IX,
            shape,
            True,
        )

    def __repr__(self) -> str:
        return repr(self._df)

    def __eq__(self, value: object) -> bool:
        if not isinstance(value, InteractionMatrix):
            logger.debug(f"Comparing {type(value)} with InteractionMatrix is not supported")
            return False
        return self._df.equals(value._df)

    def __len__(self) -> int:
        """Return the number of interactions in the matrix.

        This is distinct from the shape of the matrix, which is the number of
        users and items that has been released to the model. The length of the
        matrix is the number of interactions present in the matrix resulting
        from filter operations.
        """
        return len(self._df)

    def _get_last_n_interactions(
        self,
        by: ItemUserBasedEnum,
        n_seq_data: int,
        t_upper: None | int = None,
        id_in: None | set[int] = None,
        inplace=False,
    ) -> Self:
        if not self.has_timestamps:
            raise TimestampAttributeMissingError()
        if t_upper is None:
            t_upper = self.max_timestamp + 1  # to include the last timestamp

        interaction_m = self if inplace else self.copy()

        mask = interaction_m._df[InteractionMatrix.TIMESTAMP_IX] < t_upper
        if id_in and by == ItemUserBasedEnum.USER:
            mask = mask & interaction_m._df[InteractionMatrix.USER_IX].isin(id_in)
        elif id_in and by == ItemUserBasedEnum.ITEM:
            mask = mask & interaction_m._df[InteractionMatrix.ITEM_IX].isin(id_in)

        if by == ItemUserBasedEnum.USER:
            c_df = interaction_m._df[mask].groupby(InteractionMatrix.USER_IX).tail(n_seq_data)
        else:
            c_df = interaction_m._df[mask].groupby(InteractionMatrix.ITEM_IX).tail(n_seq_data)
        interaction_m._df = c_df

        return interaction_m

    def _get_first_n_interactions(
        self, by: ItemUserBasedEnum, n_seq_data: int, t_lower: None | int = None, inplace=False
    ) -> Self:
        if not self.has_timestamps:
            raise TimestampAttributeMissingError()
        if t_lower is None:
            t_lower = self.min_timestamp

        interaction_m = self if inplace else self.copy()

        mask = interaction_m._df[InteractionMatrix.TIMESTAMP_IX] >= t_lower
        if by == ItemUserBasedEnum.USER:
            c_df = interaction_m._df[mask].groupby(InteractionMatrix.USER_IX).head(n_seq_data)
        else:
            c_df = interaction_m._df[mask].groupby(InteractionMatrix.ITEM_IX).head(n_seq_data)
        interaction_m._df = c_df
        return interaction_m

    @property
    def item_interaction_sequence_matrix(self) -> csr_matrix:
        """Converts the interaction data into an item interaction sequence matrix.

        Dataframe values are converted into such that the row sequence is maintained and
        the item that interacted with will have the column at item_id marked with 1.
        """
        values = np.ones(self._df.shape[0])
        indices = (np.arange(self._df.shape[0]), self._df[self.ITEM_IX].to_numpy())
        shape = (self._df.shape[0], self.user_item_shape[1])

        sparse_matrix = csr_matrix((values, indices), shape=shape, dtype=values.dtype)
        return sparse_matrix

    @property
    def user_id_sequence_array(self) -> np.ndarray:
        """Array of user IDs in the order of interactions.

        :return: Numpy array of user IDs.
        :rtype: np.ndarray
        """
        return self._df[InteractionMatrix.USER_IX].to_numpy()

    @property
    def user_ids(self) -> set[int]:
        """The set of all user ID in matrix"""
        return set(self._df[InteractionMatrix.USER_IX].dropna().unique())

    @property
    def item_ids(self) -> set[int]:
        """The set of all item ID in matrix"""
        return set(self._df[InteractionMatrix.ITEM_IX].dropna().unique())

    @property
    def num_interactions(self) -> int:
        """The total number of interactions.

        :return: Total interaction count.
        :rtype: int
        """
        return len(self._df)

    @property
    def has_timestamps(self) -> bool:
        """Boolean indicating whether instance has timestamp information.

        :return: True if timestamps information is available, False otherwise.
        :rtype: bool
        """
        return self.TIMESTAMP_IX in self._df

    @property
    def min_timestamp(self) -> int:
        """The earliest timestamp in the interaction

        :return: The earliest timestamp.
        :rtype: int
        """
        if not self.has_timestamps:
            raise TimestampAttributeMissingError()
        return self._df[self.TIMESTAMP_IX].min()

    @property
    def max_timestamp(self) -> int:
        """The latest timestamp in the interaction

        :return: The latest timestamp.
        :rtype: int
        """
        if not self.has_timestamps:
            raise TimestampAttributeMissingError()
        return self._df[self.TIMESTAMP_IX].max()

    @property
    def global_num_user(self) -> int:
        return max(int(self._df[InteractionMatrix.USER_IX].max()) + 1, self.user_item_shape[0] + 1)

    @property
    def global_num_item(self) -> int:
        return max(int(self._df[InteractionMatrix.ITEM_IX].max()) + 1, self.user_item_shape[1] + 1)

    @property
    def known_num_user(self) -> int:
        """The highest known number of users

        Note that we add 1 to the max known user ID to get the number of users,
        since user IDs are zero-indexed.
        """
        max_val = self._df[(self._df != -1).all(axis=1)][InteractionMatrix.USER_IX].max()
        if pd.isna(max_val):
            return self.user_item_shape[0]
        return min(int(max_val) + 1, self.user_item_shape[0] + 1)

    @property
    def known_num_item(self) -> int:
        """The highest known user ID in the interaction matrix."""
        max_val = self._df[(self._df != -1).all(axis=1)][InteractionMatrix.ITEM_IX].max()
        if pd.isna(max_val):
            return self.user_item_shape[1]
        return min(int(max_val) + 1, self.user_item_shape[1] + 1)

    # TODO deprecate these two properties
    @property
    def max_user_id(self) -> int:
        """The highest known user ID in the interaction matrix.

        :return: The highest user ID.
        :rtype: int
        """
        max_val = self._df[self._df != -1][InteractionMatrix.USER_IX].max()
        if np.isnan(max_val):
            return -1
        return max_val

    @property
    def max_item_id(self) -> int:
        """The highest known item ID in the interaction matrix.

        In the case of an empty matrix, the highest item ID is -1. This is
        consistent with the the definition that -1 denotes the item that is
        unknown. It would be incorrect to use any other value, since 0 is a
        valid item ID.

        :return: The highest item ID.
        :rtype: int
        """
        max_val = self._df[self._df != -1][InteractionMatrix.ITEM_IX].max()
        if np.isnan(max_val):
            return -1
        return max_val

    @property
    def timestamps(self) -> pd.Series:
        """Timestamps of interactions as a pandas Series, indexed by user ID and item ID.

        :raises TimestampAttributeMissingError: If timestamp column is missing.
        :return: Interactions with composite index on (user ID, item ID)
        :rtype: pd.Series
        """
        if not self.has_timestamps:
            raise TimestampAttributeMissingError()
        index = pd.MultiIndex.from_frame(self._df[[InteractionMatrix.USER_IX, InteractionMatrix.ITEM_IX]])
        return pd.DataFrame(self._df[[InteractionMatrix.TIMESTAMP_IX]]).set_index(index)[InteractionMatrix.TIMESTAMP_IX]

    @property
    def latest_interaction_timestamps_matrix(self) -> csr_matrix:
        """A csr matrix containing the last interaction timestamp for each user, item pair.

        We only account for the last interacted timestamp making the dataset non-deduplicated.
        """
        timestamps = self.timestamps.groupby(["uid", "iid"]).max().reset_index()
        timestamp_mat = csr_matrix(
            (timestamps.ts.values, (timestamps.uid.values, timestamps.iid.values)),
            shape=self.user_item_shape,
        )

        return timestamp_mat

ITEM_IX = 'iid' class-attribute instance-attribute

USER_IX = 'uid' class-attribute instance-attribute

TIMESTAMP_IX = 'ts' class-attribute instance-attribute

INTERACTION_IX = 'interactionid' class-attribute instance-attribute

MASKED_LABEL = -1 class-attribute instance-attribute

user_item_shape instance-attribute

The shape of the interaction matrix, i.e. |user| x |item|.

values property

All user-item interactions as a sparse matrix of size (|users|, |items|).

The shape of the matrix is determined by the user_item_shape attribute. Each row represents a user and each column represents an item. The index of the rows and columns correspond to the user and item IDs respectively. An entry in the matrix is 1 if there is an interaction.

indices property

Returns a tuple of lists of user IDs and item IDs corresponding to interactions.

:return: tuple of lists of user IDs and item IDs that correspond to at least one interaction. :rtype: tuple[list[int], list[int]]

item_interaction_sequence_matrix property

Converts the interaction data into an item interaction sequence matrix.

Dataframe values are converted into such that the row sequence is maintained and the item that interacted with will have the column at item_id marked with 1.

user_id_sequence_array property

Array of user IDs in the order of interactions.

:return: Numpy array of user IDs. :rtype: np.ndarray

user_ids property

The set of all user ID in matrix

item_ids property

The set of all item ID in matrix

num_interactions property

The total number of interactions.

:return: Total interaction count. :rtype: int

has_timestamps property

Boolean indicating whether instance has timestamp information.

:return: True if timestamps information is available, False otherwise. :rtype: bool

min_timestamp property

The earliest timestamp in the interaction

:return: The earliest timestamp. :rtype: int

max_timestamp property

The latest timestamp in the interaction

:return: The latest timestamp. :rtype: int

global_num_user property

global_num_item property

known_num_user property

The highest known number of users

Note that we add 1 to the max known user ID to get the number of users, since user IDs are zero-indexed.

known_num_item property

The highest known user ID in the interaction matrix.

max_user_id property

The highest known user ID in the interaction matrix.

:return: The highest user ID. :rtype: int

max_item_id property

The highest known item ID in the interaction matrix.

In the case of an empty matrix, the highest item ID is -1. This is consistent with the the definition that -1 denotes the item that is unknown. It would be incorrect to use any other value, since 0 is a valid item ID.

:return: The highest item ID. :rtype: int

timestamps property

Timestamps of interactions as a pandas Series, indexed by user ID and item ID.

:raises TimestampAttributeMissingError: If timestamp column is missing. :return: Interactions with composite index on (user ID, item ID) :rtype: pd.Series

latest_interaction_timestamps_matrix property

A csr matrix containing the last interaction timestamp for each user, item pair.

We only account for the last interacted timestamp making the dataset non-deduplicated.

copy()

Create a deep copy of this InteractionMatrix.

Source code in src/recnexteval/matrix/interaction_matrix.py
77
78
79
def copy(self) -> Self:
    """Create a deep copy of this InteractionMatrix."""
    return deepcopy(self)

copy_df(reset_index=False)

Create a deep copy of the dataframe.

Source code in src/recnexteval/matrix/interaction_matrix.py
81
82
83
84
85
def copy_df(self, reset_index: bool = False) -> "pd.DataFrame":
    """Create a deep copy of the dataframe."""
    if reset_index:
        return deepcopy(self._df.reset_index(drop=True))
    return deepcopy(self._df)

concat(im)

Concatenate this InteractionMatrix with another.

Note

This is a inplace operation. and will modify the current object.

Source code in src/recnexteval/matrix/interaction_matrix.py
87
88
89
90
91
92
93
94
95
96
97
98
def concat(self, im: "InteractionMatrix | pd.DataFrame") -> Self:
    """Concatenate this InteractionMatrix with another.

    Note:
        This is a inplace operation. and will modify the current object.
    """
    if isinstance(im, pd.DataFrame):
        self._df = pd.concat([self._df, im])
    else:
        self._df = pd.concat([self._df, im._df])

    return self

union(im)

Combine events from this InteractionMatrix with another.

Source code in src/recnexteval/matrix/interaction_matrix.py
101
102
103
def union(self, im: "InteractionMatrix") -> Self:
    """Combine events from this InteractionMatrix with another."""
    return self + im

difference(im)

Difference between this InteractionMatrix and another.

Source code in src/recnexteval/matrix/interaction_matrix.py
105
106
107
def difference(self, im: "InteractionMatrix") -> Self:
    """Difference between this InteractionMatrix and another."""
    return self - im

nonzero()

Source code in src/recnexteval/matrix/interaction_matrix.py
139
140
def nonzero(self) -> tuple[list[int], list[int]]:
    return self.values.nonzero()

timestamps_gt(timestamp, inplace=False)

timestamps_gt(timestamp: float) -> T
timestamps_gt(
    timestamp: float, inplace: Literal[True]
) -> None

Select interactions after a given timestamp.

:param timestamp: The timestamp with which the interactions timestamp is compared. :type timestamp: float :param inplace: Apply the selection in place if True, defaults to False :type inplace: bool, optional :return: None if inplace, otherwise returns a new InteractionMatrix object :rtype: Union[InteractionMatrix, None]

Source code in src/recnexteval/matrix/filters.py
67
68
69
70
71
72
73
74
75
76
77
78
def timestamps_gt(self: T, timestamp: float, inplace: bool = False) -> None | T:
    """Select interactions after a given timestamp.

    :param timestamp: The timestamp with which
        the interactions timestamp is compared.
    :type timestamp: float
    :param inplace: Apply the selection in place if True, defaults to False
    :type inplace: bool, optional
    :return: None if `inplace`, otherwise returns a new InteractionMatrix object
    :rtype: Union[InteractionMatrix, None]
    """
    return self._timestamps_cmp(operator.gt, timestamp, inplace)

timestamps_gte(timestamp, inplace=False)

timestamps_gte(timestamp: float) -> T
timestamps_gte(
    timestamp: float, inplace: Literal[True]
) -> None

Select interactions after and including a given timestamp.

:param timestamp: The timestamp with which the interactions timestamp is compared. :type timestamp: float :param inplace: Apply the selection in place if True, defaults to False :type inplace: bool, optional :return: None if inplace, otherwise returns a new InteractionMatrix object :rtype: Union[InteractionMatrix, None]

Source code in src/recnexteval/matrix/filters.py
84
85
86
87
88
89
90
91
92
93
94
95
def timestamps_gte(self: T, timestamp: float, inplace: bool = False) -> None | T:
    """Select interactions after and including a given timestamp.

    :param timestamp: The timestamp with which
        the interactions timestamp is compared.
    :type timestamp: float
    :param inplace: Apply the selection in place if True, defaults to False
    :type inplace: bool, optional
    :return: None if `inplace`, otherwise returns a new InteractionMatrix object
    :rtype: Union[InteractionMatrix, None]
    """
    return self._timestamps_cmp(operator.ge, timestamp, inplace)

timestamps_lt(timestamp, inplace=False)

timestamps_lt(timestamp: float) -> T
timestamps_lt(
    timestamp: float, inplace: Literal[True]
) -> None

Select interactions up to a given timestamp.

:param timestamp: The timestamp with which the interactions timestamp is compared. :type timestamp: float :param inplace: Apply the selection in place if True, defaults to False :type inplace: bool, optional :return: None if inplace, otherwise returns a new InteractionMatrix object :rtype: Union[InteractionMatrix, None]

Source code in src/recnexteval/matrix/filters.py
101
102
103
104
105
106
107
108
109
110
111
112
def timestamps_lt(self: T, timestamp: float, inplace: bool = False) -> None | T:
    """Select interactions up to a given timestamp.

    :param timestamp: The timestamp with which
        the interactions timestamp is compared.
    :type timestamp: float
    :param inplace: Apply the selection in place if True, defaults to False
    :type inplace: bool, optional
    :return: None if `inplace`, otherwise returns a new InteractionMatrix object
    :rtype: Union[InteractionMatrix, None]
    """
    return self._timestamps_cmp(operator.lt, timestamp, inplace)

timestamps_lte(timestamp, inplace=False)

timestamps_lte(timestamp: float) -> T
timestamps_lte(
    timestamp: float, inplace: Literal[True]
) -> None

Select interactions up to and including a given timestamp.

:param timestamp: The timestamp with which the interactions timestamp is compared. :type timestamp: float :param inplace: Apply the selection in place if True, defaults to False :type inplace: bool, optional :return: None if inplace, otherwise returns a new InteractionMatrix object :rtype: Union[InteractionMatrix, None]

Source code in src/recnexteval/matrix/filters.py
118
119
120
121
122
123
124
125
126
127
128
129
def timestamps_lte(self: T, timestamp: float, inplace: bool = False) -> None | T:
    """Select interactions up to and including a given timestamp.

    :param timestamp: The timestamp with which
        the interactions timestamp is compared.
    :type timestamp: float
    :param inplace: Apply the selection in place if True, defaults to False
    :type inplace: bool, optional
    :return: None if `inplace`, otherwise returns a new InteractionMatrix object
    :rtype: Union[InteractionMatrix, None]
    """
    return self._timestamps_cmp(operator.le, timestamp, inplace)

get_users_n_last_interaction(n_seq_data=1, t_upper=None, user_in=None, inplace=False)

Source code in src/recnexteval/matrix/filters.py
143
144
145
146
147
148
def get_users_n_last_interaction(
    self: T, n_seq_data: int = 1, t_upper: None | int = None, user_in: None | set[int] = None, inplace: bool = False
) -> T:
    return self._get_last_n_interactions(
        by=ItemUserBasedEnum.USER, n_seq_data=n_seq_data, t_upper=t_upper, id_in=user_in, inplace=inplace
    )

get_items_n_last_interaction(n_seq_data=1, t_upper=None, item_in=None, inplace=False)

Source code in src/recnexteval/matrix/filters.py
150
151
152
153
def get_items_n_last_interaction(
    self: T, n_seq_data: int = 1, t_upper: None | int = None, item_in: None | set[int] = None, inplace: bool = False
) -> T:
    return self._get_last_n_interactions(by=ItemUserBasedEnum.ITEM, n_seq_data=n_seq_data, t_upper=t_upper, id_in=item_in, inplace=inplace)

get_users_n_first_interaction(n_seq_data=1, t_lower=None, inplace=False)

Source code in src/recnexteval/matrix/filters.py
155
156
157
158
def get_users_n_first_interaction(
    self: T, n_seq_data: int = 1, t_lower: None | int = None, inplace: bool = False
) -> T:
    return self._get_first_n_interactions(ItemUserBasedEnum.USER, n_seq_data, t_lower, inplace)

get_items_n_first_interaction(n_seq_data=1, t_lower=None, inplace=False)

Source code in src/recnexteval/matrix/filters.py
160
161
162
163
def get_items_n_first_interaction(
    self: T, n_seq_data: int = 1, t_lower: None | int = None, inplace: bool = False
) -> T:
    return self._get_first_n_interactions(ItemUserBasedEnum.ITEM, n_seq_data, t_lower, inplace)

users_in(U, inplace=False)

users_in(U: set[int]) -> T
users_in(U: set[int], inplace: Literal[False]) -> T
users_in(U: set[int], inplace: Literal[True]) -> None
Source code in src/recnexteval/matrix/filters.py
23
24
25
26
def users_in(self: T, U: set[int], inplace: bool = False) -> None | T:
    logger.debug("Performing users_in comparison")
    mask = self._df[self.USER_IX].isin(U)
    return self._apply_mask(mask, inplace=inplace)

users_not_in(U, inplace=False)

users_not_in(U: set[int]) -> T
users_not_in(U: set[int], inplace: Literal[False]) -> T
users_not_in(U: set[int], inplace: Literal[True]) -> None
Source code in src/recnexteval/matrix/filters.py
34
35
36
37
def users_not_in(self: T, U: set[int], inplace: bool = False) -> None | T:
    logger.debug("Performing users_not_in comparison")
    mask = ~self._df[self.USER_IX].isin(U)
    return self._apply_mask(mask, inplace=inplace)

items_in(id_set, inplace=False)

items_in(id_set: set[int]) -> T
items_in(id_set: set[int], inplace: Literal[False]) -> T
items_in(id_set: set[int], inplace: Literal[True]) -> None
Source code in src/recnexteval/matrix/filters.py
45
46
47
48
def items_in(self: T, id_set: set[int], inplace: bool = False) -> None | T:
    logger.debug("Performing items_in comparison")
    mask = self._df[self.ITEM_IX].isin(id_set)
    return self._apply_mask(mask, inplace=inplace)

items_not_in(id_set, inplace=False)

items_not_in(id_set: set[int]) -> T
items_not_in(
    id_set: set[int], inplace: Literal[False]
) -> T
items_not_in(
    id_set: set[int], inplace: Literal[True]
) -> None
Source code in src/recnexteval/matrix/filters.py
56
57
58
59
def items_not_in(self: T, id_set: set[int], inplace: bool = False) -> None | T:
    logger.debug("Performing items_not_in comparison")
    mask = ~self._df[self.ITEM_IX].isin(id_set)
    return self._apply_mask(mask, inplace=inplace)