code: def response_rate_text(records):
      
      if len(records) == 0:
          return None
  
      interactions = defaultdict(list)
      for r in records:
          interactions[r.correspondent_id].append(r)
  
      def _response_rate(grouped):
          received, responded = 0, 0
          conversations = _conversations(grouped)
  
          for conv in conversations:
              if len(conv) != 0:
                  first = conv[0]
                  if first.direction == 'in' and first.interaction == 'text':
                      received += 1
                      if any((i.direction == 'out' for i in conv)):
                          responded += 1
  
          return responded, received
  
      # Group all records by their correspondent, and compute the response rate
      # for each
      all_couples = map(_response_rate, list(interactions.values()))
      responded, received = map(sum, list(zip(*all_couples)))
  
      return responded / received if received != 0 else None
docs: The response rate of the user (between 0 and 1).
  
      Considers text-conversations which began with an incoming text. The response
      rate is the fraction of such conversations in which the user sent a text
      (a response).
  
      The following sequence of messages defines four conversations (``I`` for an
      incoming text, ``O`` for an outgoing text): ::
  
          I-O-I-O => Started with an incoming text and at least one outgoing text
          I-I-O-I => Started with an incoming text and at least one outgoing text
          I-I-I-I => Started with an incoming text but doesn't have outgoing texts
          O-O-I-O => Not starting with an incoming text
  
      Here, the ratio would be 2/3 as we have 3 conversations starting with an
      incoming text and 2 of them have at least one outgoing text.
  
      See :ref:`Using bandicoot <conversations-label>` for a definition of
      conversations.