Skip to content

Commit 7b14d5c

Browse files
bahrunnurBastiaan
authored andcommitted
ENH: GH11128 add weekday_name to DatetimeIndex and .dt
Completed merge of Bahrunnur's PR 'weekday-name' Moved 'enhancements' to v0.18.1.txt Added tests to pandas/tests/series/test_datetime_values.py Added weekday_name property producing 'NaT' to NaTType class Author: BastiaanBergman <Bastiaan.Bergman@gmailcom>
1 parent a69d628 commit 7b14d5c

File tree

8 files changed

+67
-6
lines changed

8 files changed

+67
-6
lines changed

doc/source/api.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,7 @@ These can be accessed like ``Series.dt.<property>``.
469469
Series.dt.days_in_month
470470
Series.dt.tz
471471
Series.dt.freq
472+
Series.dt.weekday_name
472473

473474
**Datetime Methods**
474475

@@ -1487,6 +1488,7 @@ Time/Date Components
14871488
DatetimeIndex.is_year_start
14881489
DatetimeIndex.is_year_end
14891490
DatetimeIndex.inferred_freq
1491+
DatetimeIndex.weekday_name
14901492

14911493
Selecting
14921494
~~~~~~~~~

doc/source/timeseries.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,7 @@ There are several time/date properties that one can access from ``Timestamp`` or
523523
is_quarter_end,"Logical indicating if last day of quarter (defined by frequency)"
524524
is_year_start,"Logical indicating if first day of year (defined by frequency)"
525525
is_year_end,"Logical indicating if last day of year (defined by frequency)"
526+
weekday_name,"The name of day in a week (ex: Friday)"
526527

527528
Furthermore, if you have a ``Series`` with datetimelike values, then you can access these properties via the ``.dt`` accessor, see the :ref:`docs <basics.dt_accessors>`
528529

doc/source/whatsnew/v0.18.1.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ Other Enhancements
5959
- ``pd.read_csv()`` now supports opening files using xz compression, via extension inference or explicit ``compression='xz'`` is specified; ``xz`` compressions is also supported by ``DataFrame.to_csv`` in the same way (:issue:`11852`)
6060
- ``pd.read_msgpack()`` now always gives writeable ndarrays even when compression is used (:issue:`12359`).
6161
- ``Index.take`` now handles ``allow_fill`` and ``fill_value`` consistently (:issue:`12631`)
62+
- Added ``weekday_name`` as a component to ``DatetimeIndex`` and ``.dt`` accessor. (:issue:`11128`)
6263

6364
.. ipython:: python
6465

pandas/tests/series/test_datetime_values.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ def test_dt_namespace_accessor(self):
3737
ok_for_dt = ok_for_base + ['date', 'time', 'microsecond', 'nanosecond',
3838
'is_month_start', 'is_month_end',
3939
'is_quarter_start', 'is_quarter_end',
40-
'is_year_start', 'is_year_end', 'tz']
40+
'is_year_start', 'is_year_end', 'tz',
41+
'weekday_name']
4142
ok_for_dt_methods = ['to_period', 'to_pydatetime', 'tz_localize',
4243
'tz_convert', 'normalize', 'strftime', 'round',
4344
'floor', 'ceil']

pandas/tseries/index.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ def f(self):
6161

6262
result = tslib.get_start_end_field(
6363
values, field, self.freqstr, month_kw)
64+
elif field in ['weekday_name']:
65+
result = tslib.get_date_name_field(values, field)
66+
return self._maybe_mask_results(result)
6467
else:
6568
result = tslib.get_date_field(values, field)
6669

@@ -208,7 +211,7 @@ def _join_i8_wrapper(joinf, **kwargs):
208211
'daysinmonth', 'date', 'time', 'microsecond',
209212
'nanosecond', 'is_month_start', 'is_month_end',
210213
'is_quarter_start', 'is_quarter_end', 'is_year_start',
211-
'is_year_end', 'tz', 'freq']
214+
'is_year_end', 'tz', 'freq', 'weekday_name']
212215
_is_numeric_dtype = False
213216
_infer_as_myclass = True
214217

@@ -1564,6 +1567,12 @@ def _set_freq(self, value):
15641567
'dow',
15651568
"The day of the week with Monday=0, Sunday=6")
15661569
weekday = dayofweek
1570+
1571+
weekday_name = _field_accessor(
1572+
'weekday_name',
1573+
'weekday_name',
1574+
"The name of day in a week (ex: Friday)\n\n.. versionadded:: 0.18.1")
1575+
15671576
dayofyear = _field_accessor(
15681577
'dayofyear',
15691578
'doy',

pandas/tseries/tests/test_base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def test_ops_properties(self):
3232
'is_month_start', 'is_month_end',
3333
'is_quarter_start',
3434
'is_quarter_end', 'is_year_start',
35-
'is_year_end'],
35+
'is_year_end', 'weekday_name'],
3636
lambda x: isinstance(x, DatetimeIndex))
3737

3838
def test_ops_properties_basic(self):

pandas/tseries/tests/test_timeseries.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,7 @@ def test_nat_vector_field_access(self):
959959
def test_nat_scalar_field_access(self):
960960
fields = ['year', 'quarter', 'month', 'day', 'hour', 'minute',
961961
'second', 'microsecond', 'nanosecond', 'week', 'dayofyear',
962-
'days_in_month', 'daysinmonth', 'dayofweek']
962+
'days_in_month', 'daysinmonth', 'dayofweek', 'weekday_name']
963963
for field in fields:
964964
result = getattr(NaT, field)
965965
self.assertTrue(np.isnan(result))
@@ -1852,7 +1852,7 @@ def test_timestamp_fields(self):
18521852
fields = ['dayofweek', 'dayofyear', 'week', 'weekofyear', 'quarter',
18531853
'days_in_month', 'is_month_start', 'is_month_end',
18541854
'is_quarter_start', 'is_quarter_end', 'is_year_start',
1855-
'is_year_end']
1855+
'is_year_end', 'weekday_name']
18561856
for f in fields:
18571857
expected = getattr(idx, f)[-1]
18581858
result = getattr(Timestamp(idx[-1]), f)
@@ -3541,6 +3541,15 @@ def test_datetimeindex_accessors(self):
35413541
self.assertEqual(dti.is_year_end[0], False)
35423542
self.assertEqual(dti.is_year_end[364], True)
35433543

3544+
# GH 11128
3545+
self.assertEqual(dti.weekday_name[4], u'Monday')
3546+
self.assertEqual(dti.weekday_name[5], u'Tuesday')
3547+
self.assertEqual(dti.weekday_name[6], u'Wednesday')
3548+
self.assertEqual(dti.weekday_name[7], u'Thursday')
3549+
self.assertEqual(dti.weekday_name[8], u'Friday')
3550+
self.assertEqual(dti.weekday_name[9], u'Saturday')
3551+
self.assertEqual(dti.weekday_name[10], u'Sunday')
3552+
35443553
self.assertEqual(len(dti.year), 365)
35453554
self.assertEqual(len(dti.month), 365)
35463555
self.assertEqual(len(dti.day), 365)
@@ -3558,6 +3567,7 @@ def test_datetimeindex_accessors(self):
35583567
self.assertEqual(len(dti.is_quarter_end), 365)
35593568
self.assertEqual(len(dti.is_year_start), 365)
35603569
self.assertEqual(len(dti.is_year_end), 365)
3570+
self.assertEqual(len(dti.weekday_name), 365)
35613571

35623572
dti = DatetimeIndex(freq='BQ-FEB', start=datetime(1998, 1, 1),
35633573
periods=4)

pandas/tslib.pyx

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,11 @@ class Timestamp(_Timestamp):
398398
def dayofweek(self):
399399
return self.weekday()
400400

401+
@property
402+
def weekday_name(self):
403+
out = get_date_name_field(np.array([self.value], dtype=np.int64), 'weekday_name')
404+
return out[0]
405+
401406
@property
402407
def dayofyear(self):
403408
return self._get_field('doy')
@@ -667,7 +672,7 @@ class NaTType(_NaT):
667672

668673
fields = ['year', 'quarter', 'month', 'day', 'hour',
669674
'minute', 'second', 'millisecond', 'microsecond', 'nanosecond',
670-
'week', 'dayofyear', 'days_in_month', 'daysinmonth', 'dayofweek']
675+
'week', 'dayofyear', 'days_in_month', 'daysinmonth', 'dayofweek', 'weekday_name']
671676
for field in fields:
672677
prop = property(fget=lambda self: np.nan)
673678
setattr(NaTType, field, prop)
@@ -4390,6 +4395,38 @@ def get_start_end_field(ndarray[int64_t] dtindex, object field, object freqstr=N
43904395

43914396
raise ValueError("Field %s not supported" % field)
43924397

4398+
@cython.wraparound(False)
4399+
@cython.boundscheck(False)
4400+
def get_date_name_field(ndarray[int64_t] dtindex, object field):
4401+
'''
4402+
Given a int64-based datetime index, return array of strings of date
4403+
name based on requested field (e.g. weekday_name)
4404+
'''
4405+
cdef:
4406+
_TSObject ts
4407+
Py_ssize_t i, count = 0
4408+
ndarray[object] out
4409+
pandas_datetimestruct dts
4410+
int dow
4411+
4412+
_dayname = np.array(
4413+
['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
4414+
dtype=np.str )
4415+
4416+
count = len(dtindex)
4417+
out = np.empty(count, dtype=object)
4418+
4419+
if field == 'weekday_name':
4420+
for i in range(count):
4421+
if dtindex[i] == NPY_NAT: out[i] = np.nan; continue
4422+
4423+
pandas_datetime_to_datetimestruct(dtindex[i], PANDAS_FR_ns, &dts)
4424+
dow = dayofweek(dts.year, dts.month, dts.day)
4425+
out[i] = _dayname[dow]
4426+
return out
4427+
4428+
raise ValueError("Field %s not supported" % field)
4429+
43934430

43944431
cdef inline int m8_weekday(int64_t val):
43954432
ts = convert_to_tsobject(val, None, None)

0 commit comments

Comments
 (0)