Repository: pandas-dev/pandas

Issue:
resample() silently ignores misstyped str kwargs, e.g. for label
#### Code Sample, a copy-pastable example if possible

```python
In [1]: import pandas as pd

In [2]: df = pd.DataFrame(index=pd.date_range(start='2010-01-23', periods=1000, freq='min'), data={'foo': pd.np.random.rand(1000)})

In [3]: df.resample('h').mean().tail()
Out[3]: 
                          foo
2010-01-23 12:00:00  0.477997
2010-01-23 13:00:00  0.488294
2010-01-23 14:00:00  0.426095
2010-01-23 15:00:00  0.549081
2010-01-23 16:00:00  0.466148

In [4]: df.resample('h', label='right').mean().tail()
Out[4]: 
                          foo
2010-01-23 13:00:00  0.477997
2010-01-23 14:00:00  0.488294
2010-01-23 15:00:00  0.426095
2010-01-23 16:00:00  0.549081
2010-01-23 17:00:00  0.466148

In [5]: 

In [5]: df.resample('h', label='right_wrong').mean().tail()
Out[5]: 
                          foo
2010-01-23 12:00:00  0.477997
2010-01-23 13:00:00  0.488294
2010-01-23 14:00:00  0.426095
2010-01-23 15:00:00  0.549081
2010-01-23 16:00:00  0.466148

# The last command should fail!

```
#### Problem description

Recently (and maybe many times before without noticing...) I mistyped the string passed as kwarg `label` in `resample`, e.g. `df.resample('5min', label='rigth')` and wondered later why the alignment of my resampled data with the raw data was wrong. It turns out that the actual string passed as kwarg `label` is never checked to be either `left` or `right`. Hence, if it is 

Is this on purpose, or should this be fixed?

If yes, a check could be inserted [here](https://github.com/pandas-dev/pandas/blob/ca2d2611c5a657720661990e2f3016356e577d1d/pandas/core/resample.py#L1065). Or maybe deeper in the class hierarchy? Maybe other kwargs, like `closed` could also be affected. 

If I get a pointer I could come up with a PR.

#### Output of ``pd.show_versions()``

<details>

```
INSTALLED VERSIONS
------------------
commit: None
python: 2.7.14.final.0
python-bits: 64
OS: Darwin
OS-release: 16.7.0
machine: x86_64
processor: i386
byteorder: little
LC_ALL: None
LANG: de_DE.UTF-8
LOCALE: None.None

pandas: 0.21.0
pytest: 3.2.5
pip: 9.0.1
setuptools: 36.7.2
Cython: None
numpy: 1.13.3
scipy: 1.0.0
pyarrow: 0.7.1
xarray: 0.10.0
IPython: 5.5.0
sphinx: None
patsy: 0.4.1
dateutil: 2.6.1
pytz: 2017.3
blosc: None
bottleneck: 1.2.1
tables: None
numexpr: None
feather: 0.4.0
matplotlib: 2.1.0
openpyxl: None
xlrd: 1.1.0
xlwt: None
xlsxwriter: None
lxml: None
bs4: None
html5lib: 0.999999999
sqlalchemy: None
pymysql: None
psycopg2: 2.7.3.2 (dt dec pq3 ext lo64)
jinja2: 2.9.6
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: None
```

</details>



Discussion:
I agree this should raise, and I think where you pointed (`TimeGrouper.__init__` ) is the right spot to do it.  

I also agree that `closed` can & should be checked.  `convention` looks like it raises an error eventually.
```python
df.index = df.index.to_period()
df.resample('h', convention='junk').mean().tail()
ValueError: How must be one of S or E
```

So a PR is definitely welcome!

Resolving patch:
diff --git a/pandas/core/resample.py b/pandas/core/resample.py
--- a/pandas/core/resample.py
+++ b/pandas/core/resample.py
@@ -1061,6 +1061,17 @@ class TimeGrouper(Grouper):
     def __init__(self, freq='Min', closed=None, label=None, how='mean',
                  axis=0, fill_method=None, limit=None, loffset=None,
                  kind=None, convention=None, base=0, **kwargs):
+        # Check for correctness of the keyword arguments which would
+        # otherwise silently use the default if misspelled
+        if label not in {None, 'left', 'right'}:
+            raise ValueError('Unsupported value {} for `label`'.format(label))
+        if closed not in {None, 'left', 'right'}:
+            raise ValueError('Unsupported value {} for `closed`'.format(
+                closed))
+        if convention not in {None, 'start', 'end', 'e', 's'}:
+            raise ValueError('Unsupported value {} for `convention`'
+                             .format(convention))
+
         freq = to_offset(freq)
 
         end_types = set(['M', 'A', 'Q', 'BM', 'BA', 'BQ', 'W'])


Test patch:
diff --git a/pandas/tests/test_resample.py b/pandas/tests/test_resample.py
--- a/pandas/tests/test_resample.py
+++ b/pandas/tests/test_resample.py
@@ -963,6 +963,7 @@ def test_resample_basic(self):
         rng = date_range('1/1/2000 00:00:00', '1/1/2000 00:13:00', freq='min',
                          name='index')
         s = Series(np.random.randn(14), index=rng)
+
         result = s.resample('5min', closed='right', label='right').mean()
 
         exp_idx = date_range('1/1/2000', periods=4, freq='5min', name='index')
@@ -985,6 +986,20 @@ def test_resample_basic(self):
         expect = s.groupby(grouper).agg(lambda x: x[-1])
         assert_series_equal(result, expect)
 
+    def test_resample_string_kwargs(self):
+        # Test for issue #19303
+        rng = date_range('1/1/2000 00:00:00', '1/1/2000 00:13:00', freq='min',
+                         name='index')
+        s = Series(np.random.randn(14), index=rng)
+
+        # Check that wrong keyword argument strings raise an error
+        with pytest.raises(ValueError):
+            s.resample('5min', label='righttt').mean()
+        with pytest.raises(ValueError):
+            s.resample('5min', closed='righttt').mean()
+        with pytest.raises(ValueError):
+            s.resample('5min', convention='starttt').mean()
+
     def test_resample_how(self):
         rng = date_range('1/1/2000 00:00:00', '1/1/2000 00:13:00', freq='min',
                          name='index')