diff --git a/dios/dios.py b/dios/dios.py
index 4c7d308c1870368183d8ed55d73561871cfb34c1..a88d1beaaf18e2e055003b2fa8ba2dc5189bc9e9 100644
--- a/dios/dios.py
+++ b/dios/dios.py
@@ -460,53 +460,38 @@ class DictOfSeries:
             mem += self[k].memory_usage(index=index, deep=deep)
         return mem
 
-    def foreach(self, f, *args, **kwargs):
-        self.pipe(f, *args, **kwargs)
-
-    def pipe(self, f, *args, **kwargs):
-        """
-        Call a pd.Series function on all series in the DictOfSeries
+    def apply(self, func, axis=0, raw=False, args=(), **kwds):
+        if axis in [1, 'columns']:
+            raise NotImplementedError
 
-        :param f: pd.Series function to apply on all Series
-        :param args: args for the function
-        :param kwargs: kwargs for the function
-        :return:
-        """
-        news = pd.Series()
-        newd = self.copy_empty()
-        need_dios = False
-        # return a copy nevertheless, but also run inplace if inplace=True or
-        # if the function not has this option, but work inplace.
+        elif axis in [0, 'index']:
+            pass
+        else:
+            raise ValueError(axis)
 
-        inplace = kwargs.get('inplace', False) or kwargs.get('copy', False)
+        # we cannot use self._data.apply(func=func, args=args, **kwds)
+        # because this may return a df
 
-        def getobj(k, inplace):
-            # fixme...
-            if inplace:
-                # self[k] may return a copy, so we need to get
-                # the item from the dict, by our mother class.
-                return self._data[k]
-            else:
-                return self._data.loc[k].copy()
-
-        for k in self.columns:
-            v = f(getobj(k, inplace), *args, **kwargs)
-            if inplace:
-                continue
-            if isinstance(v, pd.Series):
-                newd[k] = v
-                need_dios = True
-            else:
-                newd[k] = pd.Series(data=v)
-                news[k] = v
+        need_dios = False
+        new = []
+        for c in self.columns:
+            s = func(self[c].values if raw else self[c], *args, **kwds)
+            s = s.squeeze() if isinstance(s, pd.Series) else s
+            new.append(s)
+            try:
+                if len(s) > 1:
+                    need_dios = True
+            except TypeError:
+                pass
 
-        if inplace:
-            return None
         if need_dios:
-            return newd.squeeze()
-        if len(news) == 0:
-            return None
-        return news.squeeze()
+            dios = self.copy_empty()
+            for i, c in enumerate(self.columns):
+                dios[c] = pd.Series(new[i])
+            new = dios
+        else:
+            new = pd.Series(data=new, index=self.columns)
+        return new
 
     def _op1(self, op):
         new = self.copy_empty()