Skip to content

Commit a75d491

Browse files
committed
Merge branch 'main' into tst-str-gb
2 parents b0a82ec + a7a1410 commit a75d491

File tree

17 files changed

+390
-255
lines changed

17 files changed

+390
-255
lines changed

ci/code_checks.sh

+1-103
Large diffs are not rendered by default.

doc/source/development/contributing_codebase.rst

+1-2
Original file line numberDiff line numberDiff line change
@@ -762,8 +762,7 @@ install pandas) by typing::
762762
your installation is probably fine and you can start contributing!
763763

764764
Often it is worth running only a subset of tests first around your changes before running the
765-
entire suite (tip: you can use the `pandas-coverage app <https://pandas-coverage-12d2130077bc.herokuapp.com/>`_)
766-
to find out which tests hit the lines of code you've modified, and then run only those).
765+
entire suite.
767766

768767
The easiest way to do this is with::
769768

pandas/_libs/tslibs/offsets.pyx

+110-5
Original file line numberDiff line numberDiff line change
@@ -595,13 +595,42 @@ cdef class BaseOffset:
595595

596596
@property
597597
def rule_code(self) -> str:
598+
"""
599+
Return a string representing the base frequency.
600+
601+
See Also
602+
--------
603+
tseries.offsets.Hour.rule_code :
604+
Returns a string representing the base frequency of 'h'.
605+
tseries.offsets.Day.rule_code :
606+
Returns a string representing the base frequency of 'D'.
607+
608+
Examples
609+
--------
610+
>>> pd.offsets.Hour().rule_code
611+
'h'
612+
613+
>>> pd.offsets.Week(5).rule_code
614+
'W'
615+
"""
598616
return self._prefix
599617

600618
@cache_readonly
601619
def freqstr(self) -> str:
602620
"""
603621
Return a string representing the frequency.
604622

623+
See Also
624+
--------
625+
tseries.offsets.BusinessDay.freqstr :
626+
Return a string representing an offset frequency in Business Days.
627+
tseries.offsets.BusinessHour.freqstr :
628+
Return a string representing an offset frequency in Business Hours.
629+
tseries.offsets.Week.freqstr :
630+
Return a string representing an offset frequency in Weeks.
631+
tseries.offsets.Hour.freqstr :
632+
Return a string representing an offset frequency in Hours.
633+
605634
Examples
606635
--------
607636
>>> pd.DateOffset(5).freqstr
@@ -779,6 +808,26 @@ cdef class BaseOffset:
779808

780809
@property
781810
def nanos(self):
811+
"""
812+
Returns a integer of the total number of nanoseconds for fixed frequencies.
813+
814+
Raises
815+
------
816+
ValueError
817+
If the frequency is non-fixed.
818+
819+
See Also
820+
--------
821+
tseries.offsets.Hour.nanos :
822+
Returns an integer of the total number of nanoseconds.
823+
tseries.offsets.Day.nanos :
824+
Returns an integer of the total number of nanoseconds.
825+
826+
Examples
827+
--------
828+
>>> pd.offsets.Week(n=1).nanos
829+
ValueError: Week: weekday=None is a non-fixed frequency
830+
"""
782831
raise ValueError(f"{self} is a non-fixed frequency")
783832

784833
# ------------------------------------------------------------------
@@ -986,12 +1035,14 @@ cdef class Tick(SingleConstructorOffset):
9861035
@property
9871036
def nanos(self) -> int64_t:
9881037
"""
989-
Return an integer of the total number of nanoseconds.
1038+
Returns an integer of the total number of nanoseconds.
9901039

991-
Raises
992-
------
993-
ValueError
994-
If the frequency is non-fixed.
1040+
See Also
1041+
--------
1042+
tseries.offsets.Hour.nanos :
1043+
Returns an integer of the total number of nanoseconds.
1044+
tseries.offsets.Day.nanos :
1045+
Returns an integer of the total number of nanoseconds.
9951046

9961047
Examples
9971048
--------
@@ -2426,6 +2477,24 @@ cdef class WeekOfMonthMixin(SingleConstructorOffset):
24262477

24272478
@property
24282479
def rule_code(self) -> str:
2480+
"""
2481+
Return a string representing the base frequency.
2482+
2483+
See Also
2484+
--------
2485+
tseries.offsets.Hour.rule_code :
2486+
Returns a string representing the base frequency of 'h'.
2487+
tseries.offsets.Day.rule_code :
2488+
Returns a string representing the base frequency of 'D'.
2489+
2490+
Examples
2491+
--------
2492+
>>> pd.offsets.Week(5).rule_code
2493+
'W'
2494+
2495+
>>> pd.offsets.WeekOfMonth(n=1, week=0, weekday=0).rule_code
2496+
'WOM-1MON'
2497+
"""
24292498
weekday = int_to_weekday.get(self.weekday, "")
24302499
if self.week == -1:
24312500
# LastWeekOfMonth
@@ -2472,6 +2541,24 @@ cdef class YearOffset(SingleConstructorOffset):
24722541

24732542
@property
24742543
def rule_code(self) -> str:
2544+
"""
2545+
Return a string representing the base frequency.
2546+
2547+
See Also
2548+
--------
2549+
tseries.offsets.Hour.rule_code :
2550+
Returns a string representing the base frequency of 'h'.
2551+
tseries.offsets.Day.rule_code :
2552+
Returns a string representing the base frequency of 'D'.
2553+
2554+
Examples
2555+
--------
2556+
>>> pd.tseries.offsets.YearBegin(n=1, month=2).rule_code
2557+
'YS-FEB'
2558+
2559+
>>> pd.tseries.offsets.YearEnd(n=1, month=6).rule_code
2560+
'YE-JUN'
2561+
"""
24752562
month = MONTH_ALIASES[self.month]
24762563
return f"{self._prefix}-{month}"
24772564

@@ -3458,6 +3545,24 @@ cdef class Week(SingleConstructorOffset):
34583545

34593546
@property
34603547
def rule_code(self) -> str:
3548+
"""
3549+
Return a string representing the base frequency.
3550+
3551+
See Also
3552+
--------
3553+
tseries.offsets.Hour.name :
3554+
Returns a string representing the base frequency of 'h'.
3555+
tseries.offsets.Day.name :
3556+
Returns a string representing the base frequency of 'D'.
3557+
3558+
Examples
3559+
--------
3560+
>>> pd.offsets.Hour().rule_code
3561+
'h'
3562+
3563+
>>> pd.offsets.Week(5).rule_code
3564+
'W'
3565+
"""
34613566
suffix = ""
34623567
if self.weekday is not None:
34633568
weekday = int_to_weekday[self.weekday]

pandas/_libs/tslibs/period.pyx

+112-7
Original file line numberDiff line numberDiff line change
@@ -1913,20 +1913,58 @@ cdef class _Period(PeriodMixin):
19131913
Parameters
19141914
----------
19151915
freq : str, BaseOffset
1916-
The desired frequency. If passing a `str`, it needs to be a
1917-
valid :ref:`period alias <timeseries.period_aliases>`.
1916+
The target frequency to convert the Period object to.
1917+
If a string is provided,
1918+
it must be a valid :ref:`period alias <timeseries.period_aliases>`.
1919+
19181920
how : {'E', 'S', 'end', 'start'}, default 'end'
1919-
Start or end of the timespan.
1921+
Specifies whether to align the period to the start or end of the interval:
1922+
- 'E' or 'end': Align to the end of the interval.
1923+
- 'S' or 'start': Align to the start of the interval.
19201924

19211925
Returns
19221926
-------
1923-
resampled : Period
1927+
Period : Period object with the specified frequency, aligned to the parameter.
1928+
1929+
See Also
1930+
--------
1931+
Period.end_time : Return the end Timestamp.
1932+
Period.start_time : Return the start Timestamp.
1933+
Period.dayofyear : Return the day of the year.
1934+
Period.dayofweek : Return the day of the week.
19241935

19251936
Examples
19261937
--------
1927-
>>> period = pd.Period('2023-1-1', freq='D')
1938+
Convert a daily period to an hourly period, aligning to the end of the day:
1939+
1940+
>>> period = pd.Period('2023-01-01', freq='D')
19281941
>>> period.asfreq('h')
19291942
Period('2023-01-01 23:00', 'h')
1943+
1944+
Convert a monthly period to a daily period, aligning to the start of the month:
1945+
1946+
>>> period = pd.Period('2023-01', freq='M')
1947+
>>> period.asfreq('D', how='start')
1948+
Period('2023-01-01', 'D')
1949+
1950+
Convert a yearly period to a monthly period, aligning to the last month:
1951+
1952+
>>> period = pd.Period('2023', freq='Y')
1953+
>>> period.asfreq('M', how='end')
1954+
Period('2023-12', 'M')
1955+
1956+
Convert a monthly period to an hourly period,
1957+
aligning to the first day of the month:
1958+
1959+
>>> period = pd.Period('2023-01', freq='M')
1960+
>>> period.asfreq('h', how='start')
1961+
Period('2023-01-01 00:00', 'H')
1962+
1963+
Convert a weekly period to a daily period, aligning to the last day of the week:
1964+
1965+
>>> period = pd.Period('2023-08-01', freq='W')
1966+
>>> period.asfreq('D', how='end')
1967+
Period('2023-08-04', 'D')
19301968
"""
19311969
freq = self._maybe_convert_freq(freq)
19321970
how = validate_end_alias(how)
@@ -2000,11 +2038,44 @@ cdef class _Period(PeriodMixin):
20002038
"""
20012039
Return the year this Period falls on.
20022040

2041+
Returns
2042+
-------
2043+
int
2044+
2045+
See Also
2046+
--------
2047+
period.month : Get the month of the year for the given Period.
2048+
period.day : Return the day of the month the Period falls on.
2049+
2050+
Notes
2051+
-----
2052+
The year is based on the `ordinal` and `base` attributes of the Period.
2053+
20032054
Examples
20042055
--------
2005-
>>> period = pd.Period('2022-01', 'M')
2056+
Create a Period object for January 2023 and get the year:
2057+
2058+
>>> period = pd.Period('2023-01', 'M')
20062059
>>> period.year
2007-
2022
2060+
2023
2061+
2062+
Create a Period object for 01 January 2023 and get the year:
2063+
2064+
>>> period = pd.Period('2023', 'D')
2065+
>>> period.year
2066+
2023
2067+
2068+
Get the year for a period representing a quarter:
2069+
2070+
>>> period = pd.Period('2023Q2', 'Q')
2071+
>>> period.year
2072+
2023
2073+
2074+
Handle a case where the Period object is empty, which results in `NaN`:
2075+
2076+
>>> period = pd.Period('nan', 'M')
2077+
>>> period.year
2078+
nan
20082079
"""
20092080
base = self._dtype._dtype_code
20102081
return pyear(self.ordinal, base)
@@ -2014,11 +2085,45 @@ cdef class _Period(PeriodMixin):
20142085
"""
20152086
Return the month this Period falls on.
20162087

2088+
Returns
2089+
-------
2090+
int
2091+
2092+
See Also
2093+
--------
2094+
period.week : Get the week of the year on the given Period.
2095+
Period.year : Return the year this Period falls on.
2096+
Period.day : Return the day of the month this Period falls on.
2097+
2098+
Notes
2099+
-----
2100+
The month is based on the `ordinal` and `base` attributes of the Period.
2101+
20172102
Examples
20182103
--------
2104+
Create a Period object for January 2022 and get the month:
2105+
20192106
>>> period = pd.Period('2022-01', 'M')
20202107
>>> period.month
20212108
1
2109+
2110+
Period object with no specified frequency, resulting in a default frequency:
2111+
2112+
>>> period = pd.Period('2022', 'Y')
2113+
>>> period.month
2114+
12
2115+
2116+
Create a Period object with a specified frequency but an incomplete date string:
2117+
2118+
>>> period = pd.Period('2022', 'M')
2119+
>>> period.month
2120+
1
2121+
2122+
Handle a case where the Period object is empty, which results in `NaN`:
2123+
2124+
>>> period = pd.Period('nan', 'M')
2125+
>>> period.month
2126+
nan
20222127
"""
20232128
base = self._dtype._dtype_code
20242129
return pmonth(self.ordinal, base)

pandas/core/arrays/datetimelike.py

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import numpy as np
2121

22+
from pandas._config import using_string_dtype
2223
from pandas._config.config import get_option
2324

2425
from pandas._libs import (
@@ -1759,6 +1760,10 @@ def strftime(self, date_format: str) -> npt.NDArray[np.object_]:
17591760
dtype='object')
17601761
"""
17611762
result = self._format_native_types(date_format=date_format, na_rep=np.nan)
1763+
if using_string_dtype():
1764+
from pandas import StringDtype
1765+
1766+
return pd_array(result, dtype=StringDtype(na_value=np.nan)) # type: ignore[return-value]
17621767
return result.astype(object, copy=False)
17631768

17641769

pandas/core/arrays/datetimes.py

+16
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import numpy as np
1717

18+
from pandas._config import using_string_dtype
1819
from pandas._config.config import get_option
1920

2021
from pandas._libs import (
@@ -1332,6 +1333,13 @@ def month_name(self, locale=None) -> npt.NDArray[np.object_]:
13321333
values, "month_name", locale=locale, reso=self._creso
13331334
)
13341335
result = self._maybe_mask_results(result, fill_value=None)
1336+
if using_string_dtype():
1337+
from pandas import (
1338+
StringDtype,
1339+
array as pd_array,
1340+
)
1341+
1342+
return pd_array(result, dtype=StringDtype(na_value=np.nan)) # type: ignore[return-value]
13351343
return result
13361344

13371345
def day_name(self, locale=None) -> npt.NDArray[np.object_]:
@@ -1393,6 +1401,14 @@ def day_name(self, locale=None) -> npt.NDArray[np.object_]:
13931401
values, "day_name", locale=locale, reso=self._creso
13941402
)
13951403
result = self._maybe_mask_results(result, fill_value=None)
1404+
if using_string_dtype():
1405+
# TODO: no tests that check for dtype of result as of 2024-08-15
1406+
from pandas import (
1407+
StringDtype,
1408+
array as pd_array,
1409+
)
1410+
1411+
return pd_array(result, dtype=StringDtype(na_value=np.nan)) # type: ignore[return-value]
13961412
return result
13971413

13981414
@property

pandas/core/arrays/numpy_.py

-4
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,3 @@ def _wrap_ndarray_result(self, result: np.ndarray):
557557

558558
return TimedeltaArray._simple_new(result, dtype=result.dtype)
559559
return type(self)(result)
560-
561-
# ------------------------------------------------------------------------
562-
# String methods interface
563-
_str_na_value = np.nan

0 commit comments

Comments
 (0)