- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
Pandas 内部问题:我惊讶地发现有几次明确地将可调用对象传递给 date_parser
内pandas.read_csv
导致读取时间比简单地使用 infer_datetime_format=True
慢得多.
这是为什么?这两个选项之间的时间差异是否特定于日期格式,或者还有哪些其他因素会影响它们的相对时间?
在以下情况下,infer_datetime_format=True
传递具有指定格式的日期解析器所需的时间是其十分之一。我会天真地认为后者会更快,因为它是明确的。
文档确实指出,
[if True,] pandas will attempt to infer the format of the datetime strings in the columns, and if it can be inferred, switch to a faster method of parsing them. In some cases this can increase the parsing speed by 5-10x.
from io import StringIO
import numpy as np
import pandas as pd
np.random.seed(444)
dates = pd.date_range('1980', '2018')
df = pd.DataFrame(np.random.randint(0, 100, (len(dates), 2)),
index=dates).add_prefix('col').reset_index()
# Something reproducible to be read back in
buf = StringIO()
df.to_string(buf=buf, index=False)
def read_test(**kwargs):
# Not ideal for .seek() to eat up runtime, but alleviate
# this with more loops than needed in timing below
buf.seek(0)
return pd.read_csv(buf, sep='\s+', parse_dates=['index'], **kwargs)
# dateutil.parser.parser called in this case, according to docs
%timeit -r 7 -n 100 read_test()
18.1 ms ± 217 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit -r 7 -n 100 read_test(infer_datetime_format=True)
19.8 ms ± 516 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# Doesn't change with native Python datetime.strptime either
%timeit -r 7 -n 100 read_test(date_parser=lambda dt: pd.datetime.strptime(dt, '%Y-%m-%d'))
187 ms ± 4.05 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
infer
内部发生的事情给它这个优势。我以前的理解是,首先已经存在某种类型的推理,因为
dateutil.parser.parser
如果两者都没有通过,则使用。
read_csv()
调用
helper function依次调用
pd.core.tools.datetimes.to_datetime()
.该函数(仅可作为
pd.to_datetime()
访问)同时具有
infer_datetime_format
和一个
format
论据。
s = pd.Series(['3/11/2000', '3/12/2000', '3/13/2000']*1000)
%timeit pd.to_datetime(s,infer_datetime_format=True)
19.8 ms ± 1.54 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit pd.to_datetime(s,infer_datetime_format=False)
1.01 s ± 65.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# This was taking the longest with i/o functions,
# now it's behaving "as expected"
%timeit pd.to_datetime(s,format='%m/%d/%Y')
19 ms ± 373 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
最佳答案
您已经确定了两个重要的功能:read_csv
准备一个函数来使用 _make_date_converter
解析日期列,这总是要打电话to_datetime
( Pandas 的主要字符串到日期转换工具)。
@WillAyd 和 @bmbigbang 的答案对我来说似乎都是正确的,因为他们将缓慢的原因确定为重复调用 lambda 函数。
由于您询问有关 Pandas 源代码的更多详细信息,我将尝试检查每个 read_test
在下面拨打更多详细信息以了解我们在 to_datetime
中的最终位置以及最终为什么时间与您观察到的数据一样。read_test()
这非常快,因为在没有关于可能的日期格式的任何提示的情况下,pandas 将尝试解析类似列表的字符串列,就好像它们大约在 ISO8601 format 中一样。 (这是一个非常常见的情况)。
一头扎进to_datetime
,我们迅速到达this code branch :
if result is None and (format is None or infer_datetime_format):
result = tslib.array_to_datetime(...)
array_to_datetime
遍历字符串列以将每个字符串转换为日期时间格式。对于每一行,我们点击
_string_to_dts
在
this line ;然后我们转到另一个简短的内联代码片段(
_cstring_to_dts
),这意味着
parse_iso_8601_datetime
被调用以将字符串实际解析为日期时间对象。
parse_iso_8601_datetime
填充的 C 结构成为正确的日期时间对象,检查了一些边界)。
dateutil.parser.parser
根本没有被调用。
read_test(infer_datetime_format=True)
read_test()
一样快.
format
参数)意味着我们登陆
here在
to_datetime
:
if infer_datetime_format and format is None:
format = _guess_datetime_format_for_array(arg, dayfirst=dayfirst)
_guess_datetime_format_for_array
,它采用列中的第一个非空值并将其提供给
_guess_datetime_format
.这会尝试构建一个日期时间格式字符串以用于将来的解析。 (
My answer here 在它能够识别的格式之上有更多细节。)
infer_datetime_format
返回
False
here :
if format is not None:
# There is a special fast-path for iso8601 formatted
# datetime strings, so in those cases don't use the inferred
# format because this path makes process slower in this
# special case
format_is_iso8601 = _format_is_iso(format)
if format_is_iso8601:
require_iso8601 = not infer_datetime_format
format = None
parse_iso_8601_datetime
功能。
read_test(date_parser=lambda dt: strptime(dt, '%Y-%m-%d'))
strptime() argument 1 must be str, not numpy.ndarray
try_parse_dates
调用前
to_datetime
.
try_parse_dates
意味着不是在数组上调用,而是为
this loop 中数组的每个值重复调用 lambda 函数:
for i from 0 <= i < n:
if values[i] == '':
result[i] = np.nan
else:
result[i] = parse_date(values[i]) # parse_date is the lambda function
to_datetime
,我们现在有一个填充了
datetime
的对象数组对象。我们再次点击
array_to_datetime
,但这一次
pandas sees a date object并使用另一个函数(
pydate_to_dt64
)使其成为 datetime64 对象。
s
具有 MM/DD/YYYY 格式的日期字符串。
pd.to_datetime(s, infer_datetime_format=False)
尝试使用
parse_iso_8601_datetime
解析字符串但这失败了
ValueError
.错误处理
here :pandas 将使用
parse_datetime_string
反而。这意味着
dateutil.parser.parse
is used将字符串转换为日期时间。这就是为什么在这种情况下它很慢:在循环中重复使用 Python 函数。
pd.to_datetime(s, format='%m/%d/%Y')
之间没有太大区别和
pd.to_datetime(s, infer_datetime_format=True)
在速度方面。后者使用
_guess_datetime_format_for_array
再次推断 MM/DD/YYYY 格式。然后两者都点击
array_strptime
here :
if format is not None:
...
if result is None:
try:
result = array_strptime(arg, format, exact=exact, errors=errors)
array_strptime
是一个快速的 Cython 函数,用于将字符串数组解析为给定特定格式的日期时间结构。
关于python - 推断日期格式与传递解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48728307/
当使用模板模板参数时,我如何推断或删除模板模板的模板类型? 考虑以下 SSCCE: #include #include #include using namespace std; templat
假设我有一些特质: trait A[T] { def foo: T } 一个扩展它的类: class B[T](t: T) extends A[T] { def foo = t } 以及父特征的子特征
一边玩-rectypes在某些时候选择 OCaml 我只是迷路了。 这个表达式几乎可以打字: # fun x -> x x;; - : ('a -> 'b as 'a) -> 'b = 但是这里 O
我正在编写一个类似 CRUD 的应用程序,并且通过主键进行大量查找(主键可以有不同的类型)。所以我定义了以下类型类: {-# LANGUAGE MultiParamTypeClasses #-} cl
我已经创建了关系 A 'is functional parent of' B并定义 'has functional parent'作为 'is functional parent of' 的倒数. '
给定一个使用 Kotlin 版本 1.3.61 和 JOOQ 版本 3.13.1 的系统,这样的方法会构建 union正常查询: val selectCommonPart = coalesce
考虑以下错误代码: fun x = if (null x) then 0 else (take 50 x) : (fun (drop 50 x)) 我注意到,我可以毫无问题地将它加载到
给定一个具有以下类型的函数 a: a::x -> Bool 和以下类型的另一个函数 b: b::Bool -> y 我正在尝试找出推断以下函数类型的步骤: c =\d -> d a b 有人可以帮助解
我正在尝试使用 Infer 工具来分析我的应用代码。我关注了these steps每次我尝试运行 infer -- gradle build 时,我都会收到以下错误: infer -- gradle
所以我制作了这个模板来定义内联仿函数: template struct AsFunctor { template std::invoke_result_t operator()(A
是否可以推断 CRTP 基类中模板化成员函数的返回类型? 虽然推断参数类型效果很好,但它因返回类型而失败。考虑以下示例。 #include template struct base { tem
使用 Series.interpolate 很容易在 Pandas.DataFrame 中插入值,如何进行外推? 例如,给定一个如图所示的 DataFrame,我们如何将它外推 14 个月到 2014
我想知道为什么这不起作用(缺少参数类型)? Seq(1,2,3).toSet.map(_ + 1) 但这确实: val foo = Seq(1,2,3).toSet foo.map(_ + 1)
我没有必要使用 SQLite3 shell 工具来维护一个小型数据库。我正在使用 -header -ascii标志,尽管据我所知,这适用于任何输出选择。我正在寻找一种方法来避免对返回的任何一个值的类型
我有以下组件 type PropTypes = { items: T[], header: (item: T) => React.Element, body: (item: T) => R
我想在 Eclipse/JSDT 中指定实例变量的类型,如下例所示: /** * @constructor */ function A() { /** @type Node */
我正在用 Python 编写一个方法,它看起来像这样: def rgb_to_grayscale(image): print(image.shape) pass 此处预期的类型是 nu
我有一个 my_values 数组,我正在尝试为其推断 true_values 数组中最接近、较小的值。使用下面的 find_nearest 函数并不能完成我想要的。我如何追加它以找到最近的、较小的值
在下面的代码中: template int b(int q, const std::array& types) { int r = q; for (int t : types)
在 Pandas DataFrame 中插入 NaN 单元非常容易: In [98]: df Out[98]: neg neu pos av
我是一名优秀的程序员,十分优秀!