class_docstr: Incremental Local Outlier Factor (Incremental LOF).
  
  The Incremental Local Outlier Factor (ILOF) is an online version of the Local Outlier Factor (LOF), proposed by
  Pokrajac et al. (2017),  and is used to identify outliers based on density of local neighbors.
  
  The algorithm take into account the following elements:
      - `NewPoints`: new points;
      - `kNN(p)`: the k-nearest neighboors of `p` (the k-closest points to `p`);
      - `RkNN(p)`: the reverse-k-nearest neighboors of `p` (points that have `p` as one of their neighboors);
      - `set_upd_lrd`: Set of points that need to have the local reachability distance updated;
      - `set_upd_lof`: Set of points that need to have the local outlier factor updated.
  
  This current implementation within `River`, based on the original one in the paper, follows the following steps:
      1) Insert new data points (`NewPoints`) and calculate its distance to existing points;
      2) Update the nreaest neighboors and reverse nearest neighboors of all the points;
      3) Define sets of affected points that required updates;
      4) Calculate the reachability-distance from new point to neighboors (`NewPoints` -> `kNN(NewPoints)`)
         and from rev-neighboors to new point (`RkNN(NewPoints)` -> `NewPoints`);
      5) Update the reachability-distance for affected points: `RkNN(RkNN(NewPoints))` -> `RkNN(NewPoints)`
      6) Update local reachability distance of affected points: `lrd(set_upd_lrd)`;
      7) Update local outlier factor: `lof(set_upd_lof)`.
  
  The incremental LOF algorithm is expected to provide equivalent detection performance as the iterated static
  LOF algroithm (applied after insertion of each data record), while requiring significantly less computational time.
  Moreover, the insertion of a new data point as well as deletion of an old data point influence only a limited number
  of their closest neighbors, which means that the number of updates per such insertion/deletion does not depend
  on the total number of instances learned/in the data set.
  
  Parameters
  ----------
  n_neighbors
      The number of nearest neighbors to use for density estimation.
  distance_func
      Distance function to be used. By default, the Euclidean distance is used.
  
  Attributes
  ----------
  x_list
      A list of stored observations.
  x_batch
      A buffer to hold incoming observations until it's time to update the model.
  x_scores
      A buffer to hold incoming observations until it's time to score them.
  dist_dict
      A dictionary to hold distances between observations.
  neighborhoods
      A dictionary to hold neighborhoods for each observation.
  rev_neighborhoods
      A dictionary to hold reverse neighborhoods for each observation.
  k_dist
      A dictionary to hold k-distances for each observation.
  reach_dist
      A dictionary to hold reachability distances for each observation.
  lof
      A dictionary to hold Local Outlier Factors for each observation.
  local_reach
      A dictionary to hold local reachability distances for each observation.
  
  Examples
  --------
  
  >>> import pandas as pd
  >>> from river import anomaly
  >>> from river import datasets
  
  >>> cc_df = pd.DataFrame(datasets.CreditCard())
  
  >>> lof = anomaly.LocalOutlierFactor(n_neighbors=20)
  
  >>> for x, _ in datasets.CreditCard().take(200):
  ...     lof.learn_one(x)
  
  >>> lof.learn_many(cc_df[201:401])
  
  >>> scores = []
  >>> for x in cc_df[0][401:406]:
  ...     scores.append(lof.score_one(x))
  
  >>> [round(score, 3) for score in scores]
  [1.802, 1.936, 1.566, 1.181, 1.272]
  
  >>> X = [0.5, 0.45, 0.43, 0.44, 0.445, 0.45, 0.0]
  >>> lof = anomaly.LocalOutlierFactor()
  
  >>> for x in X[:3]:
  ...     lof.learn_one({'x': x})  # Warming up
  
  >>> for x in X:
  ...     features = {'x': x}
  ...     print(
  ...         f'Anomaly score for x={x:.3f}: {lof.score_one(features):.3f}')
  ...     lof.learn_one(features)
  Anomaly score for x=0.500: 0.000
  Anomaly score for x=0.450: 0.000
  Anomaly score for x=0.430: 0.000
  Anomaly score for x=0.440: 1.020
  Anomaly score for x=0.445: 1.032
  Anomaly score for x=0.450: 0.000
  Anomaly score for x=0.000: 0.980
  
  References
  ----------
  David Pokrajac, Aleksandar Lazarevic, and Longin Jan Latecki (2007). Incremental Local Outlier Detection for Data
  Streams. In: Proceedings of the 2007 IEEE Symposium on Computational Intelligence and Data Mining (CIDM 2007). 504-515.
  DOI: 10.1109/CIDM.2007.368917.
class_docstr_tok: ["Incremental","Local","Outlier","Factor","(","Incremental","LOF",")",".","The","Incremental","Local","Outlier","Factor","(","ILOF",")","is","an","online","version","of","the","Local","Outlier","Factor","(","LOF",")",",","proposed","by","Pokrajac","et","al",".","(","2017",")",",","and","is","used","to","identify","outliers","based","on","density","of","local","neighbors",".","The","algorithm","take","into","account","the","following","elements",":","-","`","NewPoints","`",":","new","points",";","-","`","kNN","(","p",")","`",":","the","k-nearest","neighboors","of","`","p","`","(","the","k-closest","points","to","`","p","`",")",";","-","`","RkNN","(","p",")","`",":","the","reverse-k-nearest","neighboors","of","`","p","`","(","points","that","have","`","p","`","as","one","of","their","neighboors",")",";","-","`","set_upd_lrd","`",":","Set","of","points","that","need","to","have","the","local","reachability","distance","updated",";","-","`","set_upd_lof","`",":","Set","of","points","that","need","to","have","the","local","outlier","factor","updated",".","This","current","implementation","within","`","River","`",",","based","on","the","original","one","in","the","paper",",","follows","the","following","steps",":","1",")","Insert","new","data","points","(","`","NewPoints","`",")","and","calculate","its","distance","to","existing","points",";","2",")","Update","the","nreaest","neighboors","and","reverse","nearest","neighboors","of","all","the","points",";","3",")","Define","sets","of","affected","points","that","required","updates",";","4",")","Calculate","the","reachability-distance","from","new","point","to","neighboors","(","`","NewPoints","`","-",">","`","kNN","(","NewPoints",")","`",")","and","from","rev-neighboors","to","new","point","(","`","RkNN","(","NewPoints",")","`","-",">","`","NewPoints","`",")",";","5",")","Update","the","reachability-distance","for","affected","points",":","`","RkNN","(","RkNN","(","NewPoints",")",")","`","-",">","`","RkNN","(","NewPoints",")","`","6",")","Update","local","reachability","distance","of","affected","points",":","`","lrd","(","set_upd_lrd",")","`",";","7",")","Update","local","outlier","factor",":","`","lof","(","set_upd_lof",")","`",".","The","incremental","LOF","algorithm","is","expected","to","provide","equivalent","detection","performance","as","the","iterated","static","LOF","algroithm","(","applied","after","insertion","of","each","data","record",")",",","while","requiring","significantly","less","computational","time",".","Moreover",",","the","insertion","of","a","new","data","point","as","well","as","deletion","of","an","old","data","point","influence","only","a","limited","number","of","their","closest","neighbors",",","which","means","that","the","number","of","updates","per","such","insertion\/deletion","does","not","depend","on","the","total","number","of","instances","learned\/in","the","data","set",".","Parameters","--","--","--","--","--","n_neighbors","The","number","of","nearest","neighbors","to","use","for","density","estimation",".","distance_func","Distance","function","to","be","used",".","By","default",",","the","Euclidean","distance","is","used",".","Attributes","--","--","--","--","--","x_list","A","list","of","stored","observations",".","x_batch","A","buffer","to","hold","incoming","observations","until","it","'s","time","to","update","the","model",".","x_scores","A","buffer","to","hold","incoming","observations","until","it","'s","time","to","score","them",".","dist_dict","A","dictionary","to","hold","distances","between","observations",".","neighborhoods","A","dictionary","to","hold","neighborhoods","for","each","observation",".","rev_neighborhoods","A","dictionary","to","hold","reverse","neighborhoods","for","each","observation",".","k_dist","A","dictionary","to","hold","k-distances","for","each","observation",".","reach_dist","A","dictionary","to","hold","reachability","distances","for","each","observation",".","lof","A","dictionary","to","hold","Local","Outlier","Factors","for","each","observation",".","local_reach","A","dictionary","to","hold","local","reachability","distances","for","each","observation",".","Examples","--","--","--","--",">",">",">","import","pandas","as","pd",">",">",">","from","river","import","anomaly",">",">",">","from","river","import","datasets",">",">",">","cc_df","=","pd.DataFrame","(","datasets.CreditCard","(",")",")",">",">",">","lof","=","anomaly.LocalOutlierFactor","(","n_neighbors=20",")",">",">",">","for","x",",","_","in","datasets.CreditCard","(",")",".take","(","200",")",":","...","lof.learn_one","(","x",")",">",">",">","lof.learn_many","(","cc_df","[","201:401","]",")",">",">",">","scores","=","[","]",">",">",">","for","x","in","cc_df","[","0","]","[","401:406","]",":","...","scores.append","(","lof.score_one","(","x",")",")",">",">",">","[","round","(","score",",","3",")","for","score","in","scores","]","[","1.802",",","1.936",",","1.566",",","1.181",",","1.272","]",">",">",">","X","=","[","0.5",",","0.45",",","0.43",",","0.44",",","0.445",",","0.45",",","0.0","]",">",">",">","lof","=","anomaly.LocalOutlierFactor","(",")",">",">",">","for","x","in","X","[",":3","]",":","...","lof.learn_one","(","{","'","x","'",":","x","}",")","#","Warming","up",">",">",">","for","x","in","X",":","...","features","=","{","'","x","'",":","x","}","...","print","(","...","f'Anomaly","score","for","x=","{","x",":",".3f","}",":","{","lof.score_one","(","features",")",":",".3f","}","'",")","...","lof.learn_one","(","features",")","Anomaly","score","for","x=0.500",":","0.000","Anomaly","score","for","x=0.450",":","0.000","Anomaly","score","for","x=0.430",":","0.000","Anomaly","score","for","x=0.440",":","1.020","Anomaly","score","for","x=0.445",":","1.032","Anomaly","score","for","x=0.450",":","0.000","Anomaly","score","for","x=0.000",":","0.980","References","--","--","--","--","--","David","Pokrajac",",","Aleksandar","Lazarevic",",","and","Longin","Jan","Latecki","(","2007",")",".","Incremental","Local","Outlier","Detection","for","Data","Streams",".","In",":","Proceedings","of","the","2007","IEEE","Symposium","on","Computational","Intelligence","and","Data","Mining","(","CIDM","2007",")",".","504-515",".","DOI",":","10.1109\/CIDM.2007.368917","."]
docstr: Perform initial calculations on the incoming data before applying the Incremental LOF algorithm.
  Taking the new data, it updates the neighborhoods, reverse neighborhoods, k-distances and distances between particles.
  
  Parameters
  ----------
  x_list
      A list of stored observations.
  nm
      A tuple representing the current size of the dataset.
  neighborhoods
      A dictionary of particle neighborhoods.
  rev_neighborhoods
      A dictionary of reverse particle neighborhoods.
  k_distances
      A dictionary to hold k-distances for each observation.
  dist_dict
      A dictionary of dictionaries storing distances between particles
  
  Returns
  -------
  neighborhoods
      Updated dictionary of particle neighborhoods
  rev_neighborhoods
      Updated dictionary of reverse particle neighborhoods
  k_distances
      Updated dictionary to hold k-distances for each observation
  dist_dict
      Updated dictionary of dictionaries storing distances between particles
docstr_tok: ["Perform","initial","calculations","on","the","incoming","data","before","applying","the","Incremental","LOF","algorithm",".","Taking","the","new","data",",","it","updates","the","neighborhoods",",","reverse","neighborhoods",",","k-distances","and","distances","between","particles",".","Parameters","--","--","--","--","--","x_list","A","list","of","stored","observations",".","nm","A","tuple","representing","the","current","size","of","the","dataset",".","neighborhoods","A","dictionary","of","particle","neighborhoods",".","rev_neighborhoods","A","dictionary","of","reverse","particle","neighborhoods",".","k_distances","A","dictionary","to","hold","k-distances","for","each","observation",".","dist_dict","A","dictionary","of","dictionaries","storing","distances","between","particles","Returns","--","--","--","-","neighborhoods","Updated","dictionary","of","particle","neighborhoods","rev_neighborhoods","Updated","dictionary","of","reverse","particle","neighborhoods","k_distances","Updated","dictionary","to","hold","k-distances","for","each","observation","dist_dict","Updated","dictionary","of","dictionaries","storing","distances","between","particles"]
code: def _initial_calculations(
      self,
      x_list: list,
      nm: tuple,
      neighborhoods: dict,
      rev_neighborhoods: dict,
      k_distances: dict,
      dist_dict: dict,
  ):
      """
      Perform initial calculations on the incoming data before applying the Incremental LOF algorithm.
      Taking the new data, it updates the neighborhoods, reverse neighborhoods, k-distances and distances between particles.
  
      Parameters
      ----------
      x_list
          A list of stored observations.
      nm
          A tuple representing the current size of the dataset.
      neighborhoods
          A dictionary of particle neighborhoods.
      rev_neighborhoods
          A dictionary of reverse particle neighborhoods.
      k_distances
          A dictionary to hold k-distances for each observation.
      dist_dict
          A dictionary of dictionaries storing distances between particles
  
      Returns
      -------
      neighborhoods
          Updated dictionary of particle neighborhoods
      rev_neighborhoods
          Updated dictionary of reverse particle neighborhoods
      k_distances
          Updated dictionary to hold k-distances for each observation
      dist_dict
          Updated dictionary of dictionaries storing distances between particles
  
      """
  
      n = nm[0]
      m = nm[1]
      k = self.n_neighbors
  
      # Calculate distances all particles considering new and old ones
      new_distances = [
          [i, j, self.distance(x_list[i], x_list[j])]
          for i in range(n + m)
          for j in range(i)
          if i >= n
      ]
      # Add new distances to distance dictionary
      for i in range(len(new_distances)):
          dist_dict[new_distances[i][0]][
              new_distances[i][1]
          ] = new_distances[i][2]
          dist_dict[new_distances[i][1]][
              new_distances[i][0]
          ] = new_distances[i][2]
  
      # Calculate new k-dist for each particle
      for i, inner_dict in enumerate(dist_dict.values()):
          k_distances[i] = sorted(inner_dict.values())[
              min(k, len(inner_dict.values())) - 1
          ]
  
      # Only keep particles that are neighbors in distance dictionary
      dist_dict = {
          k: {k2: v2 for k2, v2 in v.items() if v2 <= k_distances[k]}
          for k, v in dist_dict.items()
      }
  
      # Define new neighborhoods for particles
      for key, value in dist_dict.items():
          neighborhoods[key] = [index for index in value]
  
      # Define new reverse neighborhoods for particles
      for particle_id, neighbor_ids in neighborhoods.items():
          for neighbor_id in neighbor_ids:
              rev_neighborhoods[neighbor_id].append(particle_id)
  
      return neighborhoods, rev_neighborhoods, k_distances, dist_dict
  
imports: from __future__ import annotations
  import copy
  import functools
  import pandas
  from river import anomaly, utils
  from river.neighbors.base import DistanceFunc
label_desc: Use image node_id 6 for calling the LocalOutlierFactor obj's underlying member method code with example usage: obj._initial_calculations(x_list, nm, neighborhoods, rev_neighborhoods, k_distances, dist_dict) and returns: neighborhoods,  rev_neighborhoods,  k_distances,  dist_dict