Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return booleans from expression comparisons, allow for vectors to be defined in expressions #1548

Merged
merged 7 commits into from
Sep 26, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
python fix
  • Loading branch information
sc1f authored and texodus committed Sep 26, 2021
commit 22ec76b5ec968bce568f2364e5b72dd6801d2648
1 change: 0 additions & 1 deletion cpp/perspective/src/include/perspective/scalar.h
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,6 @@ t_tscalar::compare_common(const t_tscalar& rhs) const {
// text-search or profiling, and changing this behavior will result in
// a whole load of edge cases.
if (m_type != rhs.m_type) {
std::cout << "comparing mixed: " << repr() << ", " << rhs.repr() << std::endl;
COMPARER_T<unsigned char> cmp;
return cmp(m_type, rhs.m_type);
}
Expand Down
2 changes: 1 addition & 1 deletion python/perspective/perspective/src/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ scalar_to_py(const t_tscalar& scalar, bool cast_double, bool cast_string) {

switch (scalar.get_dtype()) {
case DTYPE_BOOL: {
if (scalar) {
if (scalar.as_bool()) {
return py::cast(true);
} else {
return py::cast(false);
Expand Down
53 changes: 32 additions & 21 deletions python/perspective/perspective/tests/table/test_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,9 @@ def test_view_variance_update_none(self):
table = Table(data, index="c")
view = table.view(columns=["a"], row_pivots=["b"], aggregates={"a": "var"})
result = view.to_columns()
assert result["a"] == approx([np.var([0.1, 0.5, 0.8]), None, np.var([0.5, 0.8])])
assert result["a"][0] == approx(np.var([0.1, 0.5, 0.8]))
assert result["a"][1] is None
assert result["a"][2] == approx(np.var([0.5, 0.8]))

table.update({
"a": [0.3],
Expand All @@ -589,8 +591,9 @@ def test_view_variance_update_none(self):
})

result = view.to_columns()
assert result["a"] == approx([np.var([0.5, 0.3, 0.8]), None, np.var([0.5, 0.8])])

assert result["a"][0] == approx(np.var([0.5, 0.3, 0.8]))
assert result["a"][1] is None
assert result["a"][2] == approx(np.var([0.5, 0.8]))

def test_view_variance_multi_update(self):
data = {
Expand Down Expand Up @@ -669,7 +672,10 @@ def cb1(port_id, delta):
elif flat_data["b"][i] == 0:
expected_zero.append(num)

assert result["a"] == approx([np.var(expected_total), np.var(expected_zero), np.var(expected_one), None])
assert result["a"][0] == approx(np.var(expected_total))
assert result["a"][1] == approx(np.var(expected_zero))
assert result["a"][2] == approx(np.var(expected_one))
assert result["a"][3] is None

view.on_update(cb1, mode="row")

Expand Down Expand Up @@ -768,11 +774,12 @@ def cb1(port_id, delta):
elif b[i] == 1:
expected_one.append(num)

assert result == {
"a": approx([np.var(new_a), np.var(expected_zero), np.var(expected_one), None]),
"b": [2, 0, 1, 2],
"c": [6, 9, 8, 6]
}
assert result["a"][0] == approx(np.var(new_a))
assert result["a"][1] == approx(np.var(expected_zero))
assert result["a"][2] == approx(np.var(expected_one))
assert result["a"][3] is None
assert result["b"] == [2, 0, 1, 2]
assert result["c"] == [6, 9, 8, 6]

view.on_update(cb1, mode="row")

Expand Down Expand Up @@ -853,7 +860,9 @@ def test_view_standard_deviation_update_none(self):
table = Table(data, index="c")
view = table.view(columns=["a"], row_pivots=["b"], aggregates={"a": "stddev"})
result = view.to_columns()
assert result["a"] == approx([np.std([0.1, 0.5, 0.8]), None, np.std([0.5, 0.8])])
assert result["a"][0] == approx(np.std([0.1, 0.5, 0.8]))
assert result["a"][1] is None
assert result["a"][2] == approx(np.std([0.5, 0.8]))

table.update({
"a": [0.3],
Expand All @@ -869,11 +878,9 @@ def test_view_standard_deviation_update_none(self):
})

result = view.to_columns()
assert result["a"] == approx([np.std([0.5, 0.3, 0.8]), None, np.std([0.5, 0.8])])




assert result["a"][0] == approx(np.std([0.5, 0.3, 0.8]))
assert result["a"][1] is None
assert result["a"][2] == approx(np.std([0.5, 0.8]))

def test_view_standard_deviation_multi_update(self):
data = {
Expand Down Expand Up @@ -952,7 +959,10 @@ def cb1(port_id, delta):
elif flat_data["b"][i] == 0:
expected_zero.append(num)

assert result["a"] == approx([np.std(expected_total), np.std(expected_zero), np.std(expected_one), None])
assert result["a"][0] == approx(np.std(expected_total))
assert result["a"][1] == approx(np.std(expected_zero))
assert result["a"][2] == approx(np.std(expected_one))
assert result["a"][3] is None

view.on_update(cb1, mode="row")

Expand Down Expand Up @@ -1051,11 +1061,12 @@ def cb1(port_id, delta):
elif b[i] == 1:
expected_one.append(num)

assert result == {
"a": approx([np.std(new_a), np.std(expected_zero), np.std(expected_one), None]),
"b": [2, 0, 1, 2],
"c": [6, 9, 8, 6]
}
assert result["a"][0] == approx(np.std(new_a))
assert result["a"][1] == approx(np.std(expected_zero))
assert result["a"][2] == approx(np.std(expected_one))
assert result["a"][3] is None
assert result["b"] == [2, 0, 1, 2]
assert result["c"] == [6, 9, 8, 6]

view.on_update(cb1, mode="row")

Expand Down
51 changes: 47 additions & 4 deletions python/perspective/perspective/tests/table/test_view_expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,44 @@ def test_view_expression_schema_empty(self):
assert view.to_columns() == {"a": [1, 2, 3, 4], "b": [5, 6, 7, 8]}
assert view.expression_schema() == {}

def test_view_expression_schema_all_types(self):
table = Table({"a": [1, 2, 3, 4], "b": [5, 6, 7, 8]})
view = table.view(expressions=[
'"a"',
'"b" * 0.5',
"'abcdefg'",
"True and False",
'float("a") > 2 ? null : 1',
"today()",
"now()",
"length('abcd')"
])
assert view.expression_schema() == {
'"a"': int,
'"b" * 0.5': float,
"'abcdefg'": str,
"True and False": bool,
'float("a") > 2 ? null : 1': float,
"today()": date,
"now()": datetime,
"length('abcd')": float
}

result = view.to_columns()
today = datetime(date.today().year, date.today().month, date.today().day)
del result["now()"] # no need to match datetime.now()
assert result == {
"a": [1, 2, 3, 4],
"b": [5, 6, 7, 8],
'"a"': [1, 2, 3, 4],
'"b" * 0.5': [2.5, 3, 3.5, 4],
"'abcdefg'": ['abcdefg' for _ in range(4)],
"True and False": [False for _ in range(4)],
'float("a") > 2 ? null : 1': [1, 1, None, None],
"today()": [today for _ in range(4)],
"length('abcd')": [4 for _ in range(4)]
}

def test_table_validate_expressions_with_errors(self):
table = Table({"a": [1, 2, 3, 4], "b": [5, 6, 7, 8]})
validate = table.validate_expressions(
Expand Down Expand Up @@ -66,15 +104,14 @@ def test_view_expression_create(self):
}
assert view.expression_schema() == {"computed": float}


def test_view_streaming_expression(self):
def data():
return [{"a": random()} for _ in range(50)]

table = Table(data())
view = table.view(expressions=["123"])

for i in range(5):
for _ in range(5):
table.update(data())

assert table.size() == 300
Expand All @@ -88,7 +125,7 @@ def data():
table = Table(data(), limit=50)
view = table.view(expressions=["123"])

for i in range(5):
for _ in range(5):
table.update(data())

assert table.size() == 50
Expand All @@ -102,10 +139,13 @@ def data():
table = Table(data())
view = table.view(row_pivots=["c0"], expressions=['//c0\n"a" * 2'])

for i in range(5):
for _ in range(5):
table.update(data())

assert table.size() == 300
assert view.expression_schema() == {
"c0": float
}

def test_view_streaming_expression_two(self):
def data():
Expand All @@ -118,6 +158,9 @@ def data():
table.update(data())

assert table.size() == 300
assert view.expression_schema() == {
"c0": float
}

def test_view_expression_create_no_alias(self):
table = Table({"a": [1, 2, 3, 4], "b": [5, 6, 7, 8]})
Expand Down