Keys of nested dictionaries can be arbitrary objects.

def complete_dict(
            self,
            values_dict):
        """
        Keys of nested dictionaries can be arbitrary objects.
        """
        if self.orientation != "rows":
            values_dict = transpose_nested_dictionary(values_dict)

        row_keys, column_keys = collect_nested_keys(values_dict)
        if self.verbose:
            print("[SimilarityWeightedAveraging] # rows = %d" % (len(row_keys)))
            print("[SimilarityWeightedAveraging] # columns = %d" % (len(column_keys)))
        similarities, overlaps, weights = \
            self.jacard_similarity_from_nested_dicts(values_dict)
        if self.verbose:
            print(
                "[SimilarityWeightedAveraging] Computed %d similarities between rows" % (
                    len(similarities),))
        column_to_row_values = reverse_lookup_from_nested_dict(values_dict)

        result = defaultdict(dict)

        exponent = self.similarity_exponent
        shrinkage_coef = self.shrinkage_coef
        for i, row_key in enumerate(row_keys):
            for column_key, value_triplets in column_to_row_values.items():
                total = 0
                denom = shrinkage_coef
                for (other_row_key, y) in value_triplets:
                    sample_weight = 1.0
                    sim = similarities.get((row_key, other_row_key), 0)
                    combined_weight = sim ** exponent
                    combined_weight *= sample_weight
                    total += combined_weight * y
                    denom += combined_weight
                if denom > shrinkage_coef:
                    result[row_key][column_key] = total / denom
        if self.orientation != "rows":
            result = transpose_nested_dictionary(result)
        return result