code: def churn_rate(user, summary='default', **kwargs):
      
      if len(user.records) == 0:
          return statistics([], summary=summary)
  
      query = {
          'groupby': 'week',
          'divide_by': OrderedDict([
              ('part_of_week', ['allweek']),
              ('part_of_day', ['allday'])
          ]),
          'using': 'records',
          'filter_empty': True,
          'binning': True
      }
  
      rv = grouping_query(user, query)
      weekly_positions = rv[0][1]
  
      all_positions = list(set(p for l in weekly_positions for p in l))
      frequencies = {}
      cos_dist = []
  
      for week, week_positions in enumerate(weekly_positions):
          count = Counter(week_positions)
          total = sum(count.values())
          frequencies[week] = [count.get(p, 0) / total for p in all_positions]
  
      all_indexes = range(len(all_positions))
      for f_1, f_2 in pairwise(list(frequencies.values())):
          num = sum(f_1[a] * f_2[a] for a in all_indexes)
          denom_1 = sum(f ** 2 for f in f_1)
          denom_2 = sum(f ** 2 for f in f_2)
          cos_dist.append(1 - num / (denom_1 ** .5 * denom_2 ** .5))
  
      return statistics(cos_dist, summary=summary)
docs: Computes the frequency spent at every towers each week, and returns the
      distribution of the cosine similarity between two consecutives week.
  
      .. note:: The churn rate is always computed between pairs of weeks.