Skip to content

Commit

Permalink
bump version, Merge remote-tracking branch 'pandasMap'
Browse files Browse the repository at this point in the history
  • Loading branch information
casperdcl committed Jul 30, 2016
2 parents 8e534d7 + 2eff051 commit 96dc152
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 47 deletions.
5 changes: 2 additions & 3 deletions README.rst
Expand Up @@ -492,15 +492,14 @@ for ``DataFrame.progress_apply`` and ``DataFrameGroupBy.progress_apply``:
import numpy as np
from tqdm import tqdm
...
df = pd.DataFrame(np.random.randint(0, 100, (100000, 6)))
# Register `pandas.progress_apply` with `tqdm`
# Register `pandas.progress_apply` and `pandas.Series.map_apply` with `tqdm`
# (can use `tqdm_gui`, `tqdm_notebook`, optional kwargs, etc.)
tqdm.pandas(desc="my bar!")
# Now you can use `progress_apply` instead of `apply`
# and `progress_map` instead of `map`
df.progress_apply(lambda x: x**2)
# can also groupby:
# df.groupby(0).progress_apply(lambda x: x**2)
Expand Down
9 changes: 5 additions & 4 deletions examples/pandas_progress_apply.py
@@ -1,14 +1,15 @@
import pandas as pd
import numpy as np
from tqdm import tqdm, tqdm_pandas
from tqdm import tqdm

df = pd.DataFrame(np.random.randint(0, 100, (100000, 6)))

# Create and register a new `tqdm` instance with `pandas`
# (can use tqdm_gui, optional kwargs, etc.)
tqdm_pandas(tqdm())
# Register `pandas.progress_apply` and `pandas.Series.map_apply` with `tqdm`
# (can use `tqdm_gui`, `tqdm_notebook`, optional kwargs, etc.)
tqdm.pandas(desc="my bar!")

# Now you can use `progress_apply` instead of `apply`
# and `progress_map` instead of `map`
df.progress_apply(lambda x: x**2)
# can also groupby:
# df.groupby(0).progress_apply(lambda x: x**2)
Expand Down
95 changes: 56 additions & 39 deletions tqdm/_tqdm.py
Expand Up @@ -379,55 +379,72 @@ def pandas(tclass, *targs, **tkwargs):
"""
from pandas.core.frame import DataFrame
from pandas.core.series import Series
from pandas.core.groupby import DataFrameGroupBy, SeriesGroupBy
from pandas.core.groupby import DataFrameGroupBy
from pandas.core.groupby import SeriesGroupBy
from pandas.core.groupby import GroupBy
from pandas.core.groupby import PanelGroupBy
from pandas import Panel

deprecated_t = [tkwargs.pop('deprecated_t', None)]

def inner(df, func, *args, **kwargs):
"""
Parameters
----------
df : (DataFrame|Series)[GroupBy]
Data (may be grouped).
func : function
To be applied on the (grouped) data.
*args, *kwargs : optional
Transmitted to `df.apply()`.
"""
# Precompute total iterations
total = getattr(df, 'ngroups', None)
if total is None: # not grouped
total = len(df) if isinstance(df, Series) \
else df.size // len(df)
else:
total += 1 # pandas calls update once too many
def inner_generator(df_function='apply'):
def inner(df, func, *args, **kwargs):
"""
Parameters
----------
df : (DataFrame|Series)[GroupBy]
Data (may be grouped).
func : function
To be applied on the (grouped) data.
*args, *kwargs : optional
Transmitted to `df.apply()`.
"""
# Precompute total iterations
total = getattr(df, 'ngroups', None)
if total is None: # not grouped
total = len(df) if isinstance(df, Series) \
else df.size // len(df)
else:
total += 1 # pandas calls update once too many

# Init bar
if deprecated_t[0] is not None:
t = deprecated_t[0]
deprecated_t[0] = None
else:
t = tclass(*targs, total=total, **tkwargs)
# Init bar
if deprecated_t[0] is not None:
t = deprecated_t[0]
deprecated_t[0] = None
else:
t = tclass(*targs, total=total, **tkwargs)

# Define bar updating wrapper
def wrapper(*args, **kwargs):
t.update()
return func(*args, **kwargs)
# Define bar updating wrapper
def wrapper(*args, **kwargs):
t.update()
return func(*args, **kwargs)

# Apply the provided function (in *args and **kwargs)
# on the df using our wrapper (which provides bar updating)
result = df.apply(wrapper, *args, **kwargs)
# Apply the provided function (in *args and **kwargs)
# on the df using our wrapper (which provides bar updating)
result = getattr(df, df_function)(wrapper, *args, **kwargs)

# Close bar and return pandas calculation result
t.close()
return result
# Close bar and return pandas calculation result
t.close()
return result
return inner

# Monkeypatch pandas to provide easy methods
# Enable custom tqdm progress in pandas!
DataFrame.progress_apply = inner
DataFrameGroupBy.progress_apply = inner
Series.progress_apply = inner
SeriesGroupBy.progress_apply = inner
Series.progress_apply = inner_generator()
SeriesGroupBy.progress_apply = inner_generator()
Series.progress_map = inner_generator('map')
SeriesGroupBy.progress_map = inner_generator('map')

DataFrame.progress_apply = inner_generator()
DataFrameGroupBy.progress_apply = inner_generator()
DataFrame.progress_applymap = inner_generator('applymap')

Panel.progress_apply = inner_generator()
PanelGroupBy.progress_apply = inner_generator()

GroupBy.progress_apply = inner_generator()
GroupBy.progress_aggregate = inner_generator('aggregate')
GroupBy.progress_transform = inner_generator('transform')

def __init__(self, iterable=None, desc=None, total=None, leave=True,
file=sys.stderr, ncols=None, mininterval=0.1,
Expand Down
2 changes: 1 addition & 1 deletion tqdm/_version.py
Expand Up @@ -8,7 +8,7 @@
__all__ = ["__version__"]

# major, minor, patch, -extra
version_info = 4, 8, 1
version_info = 4, 8, 2

# Nice string for the version
__version__ = '.'.join(map(str, version_info))
Expand Down
20 changes: 20 additions & 0 deletions tqdm/tests/tests_pandas.py
Expand Up @@ -60,6 +60,26 @@ def test_pandas_apply():
'100% at least twice', our_file.read()))


@with_setup(pretest, posttest)
def test_pandas_map():
""" Test pandas.Series.progress_map """
try:
from numpy.random import randint
import pandas as pd
except:
raise SkipTest

with closing(StringIO()) as our_file:
tqdm.pandas(file=our_file, leave=True, ascii=True)
dfs = pd.DataFrame(randint(0, 50, (500, 3)),
columns=list('abc'))
dfs.a.progress_map(lambda x: None)

if our_file.getvalue().count('100%') < 1:
raise AssertionError("\nExpected:\n{0}\nIn:{1}\n".format(
'100% at least twice', our_file.getvalue()))


@with_setup(pretest, posttest)
def test_pandas_leave():
""" Test pandas with `leave=True` """
Expand Down

0 comments on commit 96dc152

Please sign in to comment.