Repository: blaze/blaze

Issue:
Nested transformations don't work
Transformations containing other transformations are not currently possible. They'll be implemented in #568. Here's an example of something that will work after that PR:

``` python
d = {'timestamp': [1379613528, 1379620047], 'platform': ["Linux", "Windows"]}
df = DataFrame(d)
t = TableSymbol('t', discover(df))
t = transform(t, timestamp=t.timestamp.map(datetime.fromtimestamp,
                                            schema='{timestamp: datetime}'))
expr = transform(t, date=t.timestamp.map(lambda x: x.date(),
                                            schema='{date: datetime}'))
result = compute(expr, df)
df['timestamp'] = df.timestamp.map(datetime.fromtimestamp)
df['date'] = df.timestamp.map(lambda x: x.date())
assert str(result) == str(df)
```



Discussion:

Resolving patch:
diff --git a/blaze/compute/pandas.py b/blaze/compute/pandas.py
--- a/blaze/compute/pandas.py
+++ b/blaze/compute/pandas.py
@@ -22,6 +22,7 @@
 from pandas.core.groupby import DataFrameGroupBy, SeriesGroupBy
 import numpy as np
 from collections import defaultdict
+from toolz import merge as merge_dicts
 
 from ..api.into import into
 from ..dispatch import dispatch
@@ -333,7 +334,13 @@ def compute_one(t, df, **kwargs):
 
 @dispatch(Map, Series)
 def compute_one(t, df, **kwargs):
-    return df.map(t.func)
+    result = df.map(t.func)
+    try:
+        result.name = t.name
+    except NotImplementedError:
+        # We don't have a schema, but we should still be able to map
+        result.name = df.name
+    return result
 
 
 @dispatch(Apply, (Series, DataFrame))
@@ -341,10 +348,11 @@ def compute_one(t, df, **kwargs):
     return t.func(df)
 
 
-@dispatch(Merge, DataFrame)
-def compute_one(t, df, **kwargs):
+@dispatch(Merge, NDFrame)
+def compute_one(t, df, scope=None, **kwargs):
     subexpression = common_subexpression(*t.children)
-    children = [compute(child, {subexpression: df}) for child in t.children]
+    scope = merge_dicts(scope or {}, {subexpression: df})
+    children = [compute(child, scope) for child in t.children]
     return pd.concat(children, axis=1)
 
 


Test patch:
diff --git a/blaze/compute/tests/test_pandas_compute.py b/blaze/compute/tests/test_pandas_compute.py
--- a/blaze/compute/tests/test_pandas_compute.py
+++ b/blaze/compute/tests/test_pandas_compute.py
@@ -2,12 +2,13 @@
 
 import pytest
 
+from datetime import datetime
 import pandas as pd
 import numpy as np
 from pandas import DataFrame, Series
 
 from blaze.compute.core import compute
-from blaze import dshape, Table
+from blaze import dshape, Table, discover, transform
 from blaze.expr import TableSymbol, join, by, summary, Distinct
 from blaze.expr import (merge, exp, mean, count, nunique, Apply, union, sum,
                         min, max, any, all, Projection)
@@ -501,3 +502,29 @@ def test_summary_by_reduction_arithmetic():
 def test_summary():
     expr = summary(count=t.id.count(), sum=t.amount.sum())
     assert str(compute(expr, df)) == str(Series({'count': 3, 'sum': 350}))
+
+
+def test_dplyr_transform():
+    df = DataFrame({'timestamp': pd.date_range('now', periods=5)})
+    t = TableSymbol('t', discover(df))
+    expr = transform(t, date=t.timestamp.map(lambda x: x.date(),
+                                             schema='{date: datetime}'))
+    lhs = compute(expr, df)
+    rhs = pd.concat([df, Series(df.timestamp.map(lambda x: x.date()),
+                                name='date').to_frame()], axis=1)
+    assert str(lhs) == str(rhs)
+
+
+def test_nested_transform():
+    d = {'timestamp': [1379613528, 1379620047], 'platform': ["Linux",
+                                                             "Windows"]}
+    df = DataFrame(d)
+    t = TableSymbol('t', discover(df))
+    t = transform(t, timestamp=t.timestamp.map(datetime.fromtimestamp,
+                                               schema='{timestamp: datetime}'))
+    expr = transform(t, date=t.timestamp.map(lambda x: x.date(),
+                                             schema='{date: datetime}'))
+    result = compute(expr, df)
+    df['timestamp'] = df.timestamp.map(datetime.fromtimestamp)
+    df['date'] = df.timestamp.map(lambda x: x.date())
+    assert str(result) == str(df)