/
githubmirror
/
pandas
Обзор
Документация
Войти
/
githubmirror
/
pandas
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
asv_bench/benchmarks/strings.py
300 строк
8 KB
jbrockmendel
REF: get rid of StringArrayNumpySemantics (#62149)
02 сен 2025, 19:41
Не верифицирован
02 сен 2025, 19:41
aabbbc5
Код
Авторство
О чём код?
import warnings import numpy as np from pandas import ( NA, Categorical, DataFrame, Index, Series, StringDtype, ) from pandas.arrays import StringArray class Dtypes: params = ["str", "string[python]", "string[pyarrow]"] param_names = ["dtype"] def setup(self, dtype): try: self.s = Series( Index([f"i-{i}" for i in range(10000)], dtype=object)._values, dtype=dtype, ) except ImportError as err: raise NotImplementedError from err class Construction: params = ( ["series", "frame", "categorical_series"], ["str", "string[python]", "string[pyarrow]"], ) param_names = ["pd_type", "dtype"] pd_mapping = {"series": Series, "frame": DataFrame, "categorical_series": Series} dtype_mapping = {"str": "str", "string[python]": object, "string[pyarrow]": object} def setup(self, pd_type, dtype): series_arr = np.array( [str(i) * 10 for i in range(100_000)], dtype=self.dtype_mapping[dtype] ) if pd_type == "series": self.arr = series_arr elif pd_type == "frame": self.arr = series_arr.reshape((50_000, 2)).copy() elif pd_type == "categorical_series": # GH37371. Testing construction of string series/frames from ExtensionArrays self.arr = Categorical(series_arr) def time_construction(self, pd_type, dtype): self.pd_mapping[pd_type](self.arr, dtype=dtype) def peakmem_construction(self, pd_type, dtype): self.pd_mapping[pd_type](self.arr, dtype=dtype) class Methods(Dtypes): def time_center(self, dtype): self.s.str.center(100) def time_count(self, dtype): self.s.str.count("A") def time_endswith(self, dtype): self.s.str.endswith("A") def time_extract(self, dtype): with warnings.catch_warnings(record=True): self.s.str.extract("(\\w*)A(\\w*)") def time_findall(self, dtype): self.s.str.findall("[A-Z]+") def time_find(self, dtype): self.s.str.find("[A-Z]+") def time_rfind(self, dtype): self.s.str.rfind("[A-Z]+") def time_fullmatch(self, dtype): self.s.str.fullmatch("A") def time_get(self, dtype): self.s.str.get(0) def time_len(self, dtype): self.s.str.len() def time_join(self, dtype): self.s.str.join(" ") def time_match(self, dtype): self.s.str.match("A") def time_normalize(self, dtype): self.s.str.normalize("NFC") def time_pad(self, dtype): self.s.str.pad(100, side="both") def time_partition(self, dtype): self.s.str.partition("A") def time_rpartition(self, dtype): self.s.str.rpartition("A") def time_replace(self, dtype): self.s.str.replace("A", "\x01\x01") def time_translate(self, dtype): self.s.str.translate({"A": "\x01\x01"}) def time_slice(self, dtype): self.s.str.slice(5, 15, 2) def time_startswith(self, dtype): self.s.str.startswith("A") def time_strip(self, dtype): self.s.str.strip("A") def time_rstrip(self, dtype): self.s.str.rstrip("A") def time_lstrip(self, dtype): self.s.str.lstrip("A") def time_title(self, dtype): self.s.str.title() def time_upper(self, dtype): self.s.str.upper() def time_lower(self, dtype): self.s.str.lower() def time_wrap(self, dtype): self.s.str.wrap(10) def time_zfill(self, dtype): self.s.str.zfill(10) def time_isalnum(self, dtype): self.s.str.isalnum() def time_isalpha(self, dtype): self.s.str.isalpha() def time_isdecimal(self, dtype): self.s.str.isdecimal() def time_isdigit(self, dtype): self.s.str.isdigit() def time_islower(self, dtype): self.s.str.islower() def time_isnumeric(self, dtype): self.s.str.isnumeric() def time_isspace(self, dtype): self.s.str.isspace() def time_istitle(self, dtype): self.s.str.istitle() def time_isupper(self, dtype): self.s.str.isupper() class Repeat: params = ["int", "array"] param_names = ["repeats"] def setup(self, repeats): N = 10**5 self.s = Series(Index([f"i-{i}" for i in range(N)], dtype=object)) repeat = {"int": 1, "array": np.random.randint(1, 3, N)} self.values = repeat[repeats] def time_repeat(self, repeats): self.s.str.repeat(self.values) class Cat: params = ([0, 3], [None, ","], [None, "-"], [0.0, 0.001, 0.15]) param_names = ["other_cols", "sep", "na_rep", "na_frac"] def setup(self, other_cols, sep, na_rep, na_frac): N = 10**5 mask_gen = lambda: np.random.choice([True, False], N, p=[1 - na_frac, na_frac]) self.s = Series(Index([f"i-{i}" for i in range(N)], dtype=object)).where( mask_gen() ) if other_cols == 0: # str.cat self-concatenates only for others=None self.others = None else: self.others = DataFrame( { i: Index([f"i-{i}" for i in range(N)], dtype=object).where( mask_gen() ) for i in range(other_cols) } ) def time_cat(self, other_cols, sep, na_rep, na_frac): # before the concatenation (one caller + other_cols columns), the total # expected fraction of rows containing any NaN is: # reduce(lambda t, _: t + (1 - t) * na_frac, range(other_cols + 1), 0) # for other_cols=3 and na_frac=0.15, this works out to ~48% self.s.str.cat(others=self.others, sep=sep, na_rep=na_rep) class Contains(Dtypes): params = (Dtypes.params, [True, False]) param_names = ["dtype", "regex"] def setup(self, dtype, regex): super().setup(dtype) def time_contains(self, dtype, regex): self.s.str.contains("A", regex=regex) class Split(Dtypes): params = (Dtypes.params, [True, False]) param_names = ["dtype", "expand"] def setup(self, dtype, expand): super().setup(dtype) self.s = self.s.str.join("--") def time_split(self, dtype, expand): self.s.str.split("--", expand=expand) def time_rsplit(self, dtype, expand): self.s.str.rsplit("--", expand=expand) class Extract(Dtypes): params = (Dtypes.params, [True, False]) param_names = ["dtype", "expand"] def setup(self, dtype, expand): super().setup(dtype) def time_extract_single_group(self, dtype, expand): with warnings.catch_warnings(record=True): self.s.str.extract("(\\w*)A", expand=expand) class Dummies(Dtypes): def setup(self, dtype): super().setup(dtype) N = len(self.s) // 5 self.s = self.s[:N].str.join("|") def time_get_dummies(self, dtype): self.s.str.get_dummies("|") class Encode: def setup(self): self.ser = Series(Index([f"i-{i}" for i in range(10_000)], dtype=object)) def time_encode_decode(self): self.ser.str.encode("utf-8").str.decode("utf-8") class Slice: def setup(self): self.s = Series(["abcdefg", np.nan] * 500000) def time_vector_slice(self): # GH 2602 self.s.str[:5] class Iter(Dtypes): def time_iter(self, dtype): for i in self.s: pass class StringArrayConstruction: def setup(self): self.series_arr = np.array([str(i) * 10 for i in range(10**5)], dtype=object) self.series_arr_nan = np.concatenate([self.series_arr, np.array([NA] * 1000)]) def time_string_array_construction(self): StringArray(self.series_arr, dtype=StringDtype()) def time_string_array_with_nan_construction(self): StringArray(self.series_arr_nan, dtype=StringDtype()) def peakmem_stringarray_construction(self): StringArray(self.series_arr, dtype=StringDtype())