def get_top_two_tags_for_note(
  noteStats: pd.DataFrame,
  minRatingsToGetTag: int,
  minTagsNeededToGetStatus: int,
  tagsConsideredInTiebreakOrder: List[str],
) -> pd.DataFrame:
  """Given a scoredNotes DataFrame, determine which two
  explanation tags to assign to each note based on its ratings.

  See https://twitter.github.io/communitynotes/ranking-notes/#determining-note-status-explanation-tags

  Args:
      noteStats (pd.DataFrame): row of the scoredNotes dataframe, including a count of each tag
      minRatingsToGetTag (int): min ratings needed
      minTagsNeededForStatus (int): min tags needed before a note gets a status
      tagsConsideredInTiebreakOrder (list[str]): set of tags to consider for *all* notes

  Returns:
      A dataframe back, filtered to just the rows that are assigned tags, with
      c.firstTagKey and c.secondTagKey columns set, and the index set to noteId.
  """
  assert (
    minTagsNeededToGetStatus == 2
  ), f"minTagsNeededToGetStatus was {minTagsNeededToGetStatus} but only implemented for minTagsNeededToGetStatus=2"

  with c.time_block("NH Tags: Top 2 per note"):
    noteStats.set_index(c.noteIdKey, inplace=True)
    noteTagTotals = noteStats[tagsConsideredInTiebreakOrder[::-1]]  # Put winning tags at front.

    # Filter tags and apply minimum rating threshold
    filteredTags = noteTagTotals.where(lambda x: x >= minRatingsToGetTag)
    filteredTags.dropna(
      thresh=minTagsNeededToGetStatus, inplace=True
    )  # only keep rows with at least 2 non-NaN entries

    negativeTags = -1 * filteredTags.to_numpy(dtype=np.float64)

    # Create a small value for tie-breaking, proportional to the column indices
    # The small value should be smaller than the smallest difference between any two elements (ints)
    epsilon = 1e-3
    tieBreakers = np.arange(negativeTags.shape[1]) * epsilon

    # Add the tie_breaker to the array
    negativeTieBrokenTags = tieBreakers + negativeTags

    # Fill nans with 0 (higher than all other values with nonzero tag counts)
    negativeTieBrokenTags = np.nan_to_num(negativeTieBrokenTags)

    # Use argsort on the modified array
    sortedIndices = np.argsort(negativeTieBrokenTags, axis=1)

    # Extract indices of the two largest values in each row
    topTwoIndices = sortedIndices[:, :2]
    noteTopTags = pd.DataFrame(
      np.array(filteredTags.columns)[topTwoIndices], columns=[c.firstTagKey, c.secondTagKey]
    )
    noteTopTags[c.noteIdKey] = filteredTags.index
    noteTopTags.index = filteredTags.index

    return noteTopTags
Given a scoredNotes DataFrame, determine which two
  explanation tags to assign to each note based on its ratings.

  See https://twitter.github.io/communitynotes/ranking-notes/#determining-note-status-explanation-tags

  Args:
      noteStats (pd.DataFrame): row of the scoredNotes dataframe, including a count of each tag
      minRatingsToGetTag (int): min ratings needed
      minTagsNeededForStatus (int): min tags needed before a note gets a status
      tagsConsideredInTiebreakOrder (list[str]): set of tags to consider for *all* notes

  Returns:
      A dataframe back, filtered to just the rows that are assigned tags, with
      c.firstTagKey and c.secondTagKey columns set, and the index set to noteId.
  
sourcecode/scoring/explanation_tags.py