def execute(aggregation_type, cell_coos, table):
    """Executes predicted structure against a table to produce the denotation."""
    values = _collect_cells_from_table(cell_coos, table)
    values_parsed = [_parse_value(value) for value in values]
    values_parsed = tuple(values_parsed)
    if aggregation_type == _Answer.NONE:
        # In this case there is no aggregation
        return values_parsed, values
    else:  # Should perform aggregation.
        if not values and (aggregation_type == _Answer.AVERAGE
                           or aggregation_type == _Answer.SUM):
            # Summing or averaging an empty set results in an empty set.
            # NB: SQL returns null for sum over an empty set.
            return tuple(), values
        if aggregation_type == _Answer.COUNT:
            denotation = len(values)
        else:
            # In this case all values must be numbers (to be summed or averaged).
            try:
                values_num = [
                    text_utils.convert_to_float(value) for value in values
                ]
            except ValueError:
                return values_parsed, values
            if aggregation_type == _Answer.SUM:
                denotation = sum(values_num)
            elif aggregation_type == _Answer.AVERAGE:
                denotation = sum(values_num) / len(values_num)
            else:
                raise ValueError('Unknwon aggregation type: %s' %
                                 aggregation_type)
        return tuple([float(denotation)]), values
def _get_float_answer(table, answer_coordinates, aggregation_op):
    """Applies operation to produce reference float answer."""
    if not answer_coordinates:
        if aggregation_op == _Aggregation.COUNT:
            return 0.0
        else:
            return _NAN

    # Count can support non numeric answers.
    if aggregation_op == _Aggregation.COUNT:
        return float(len(answer_coordinates))

    # If we have just one answer, if float returns it or try a conversion.
    values = [table['rows'][i][j] for (i, j) in answer_coordinates]
    if len(answer_coordinates) == 1:
        try:
            return text_utils.convert_to_float(values[0])
        except ValueError as e:
            if aggregation_op != _Aggregation.NONE:
                raise e

    if aggregation_op == _Aggregation.NONE:
        return None

    # Other aggregation only support numeric values. Bail out if we have strings.
    if not all((isinstance(v, (int, float)) for v in values)):
        return None

    if aggregation_op == _Aggregation.SUM:
        return float(sum(values))
    elif aggregation_op == _Aggregation.AVERAGE:
        return sum(values) / len(answer_coordinates)
    else:
        raise ValueError(f'Unknown aggregation: {aggregation_op}')
Exemple #3
0
def _has_single_float_answer_equal_to(question, target):
    """Returns true if the question has a single answer whose value equals to target."""
    if len(question.answer.answer_texts) != 1:
        return False
    try:
        float_value = text_utils.convert_to_float(
            question.answer.answer_texts[0])
        # In general answer_float is derived by applying the same conver_to_float
        # function at interaction creation time, hence here we use exact match to
        # avoid any false positive.
        return text_utils.to_float32(float_value) == text_utils.to_float32(
            target)
    except ValueError:
        return False
def _safe_convert_to_float(value):
    float_value = text_utils.convert_to_float(value)
    if math.isnan(float_value):
        raise ValueError('Value is NaN %s' % value)
    return float_value
Exemple #5
0
def _to_floats(values):
    return [text_utils.convert_to_float(v) for v in values]
Exemple #6
0
 def test_float_conversion_fails(self):
     with self.assertRaises(ValueError):
         text_utils.convert_to_float("hello")
Exemple #7
0
 def test_float_conversion(self, value, expected):
     self.assertEqual(expected, text_utils.convert_to_float(value))
Exemple #8
0
def _parse_answer_float(answer):
    if len(answer.answer_texts) > 1:
        raise ValueError("Cannot convert to multiple answers to single float")
    float_value = text_utils.convert_to_float(answer.answer_texts[0])
    answer.float_value = float_value