【问题标题】:pandas to_datetime() not detecting columns熊猫 to_datetime() 未检测到列
【发布时间】:2018-11-12 06:31:41
【问题描述】:

我有三列(h1、h2、h3)分别代表日、月和年,例如

import pandas as pd

df = pd.DataFrame({
    'h1': [1,2,3],
    'h2': [1,2,3],
    'h3': [2000,2001,2002]
})

当我表演时:

pd.to_datetime(df[['h1', 'h2', 'h3']])

这会导致错误:ValueError: to assemble mappings requires at least that [year, month, day] be specified: [day,month,year] is missing 但是当我重命名列然后执行 pd.to_datetime 例如

df=df.rename(columns ={'h1':'day', 'h2':'month', 'h3': 'year'})
df["date_col"] =pd.to_datetime(df[['day','month','year']])

在上面我得到了年份列,我们必须这样做吗?或者是否可以提供一种格式,以便可以将列分别检测为日、月、年? 谢谢。

【问题讨论】:

  • 使用 pandas 库的 to_datetime 方法从这三列(h1、h2、h3)创建日期
  • 当然,它工作正常,但我不想在创建列之前重命名它
  • 太好了,谢谢。这种理解效果很好。
  • 我已将您的问题格式化为我认为更具可读性的方式。我还删除了我的答案的某些部分,因为它们只是副本。希望你能像我一样发现它更具可读性,并可能在未来应用它:)

标签: python pandas


【解决方案1】:

总结:

正如文档所说,您重命名列的方法已经很聪明了:

例子

从 DataFrame 的多列中组装日期时间。按键 可以是常见的缩写,如 [‘year’, ‘month’, ‘day’, ‘minute’, ‘second’, ‘ms’, ‘us’, ‘ns’]) 或相同的复数形式

但也有一些选择。以我的经验,使用 zip 的列表理解非常快(对于小型集合)。使用大约 3000 行数据重命名列变得最快。查看图表,重命名的惩罚对于小集合很难,但对大集合有补偿。

替代品

pd.to_datetime(['-'.join(map(str,i)) for i in zip(df['h3'],df['h2'],df['h1'])])
pd.to_datetime(['-'.join(i) for i in df[['h3', 'h2', 'h1']].values.astype(str)])
df[['h3','h2','h1']].astype(str).apply(lambda x: pd.to_datetime('-'.join(x)), 1)
pd.to_datetime(df[['h1','h2','h3']].rename(columns={'h1':'day', 'h2':'month','h3':'year'}))

Win10 计时:

#df = pd.concat([df]*1000)
2.74 ms ± 33.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
8.08 ms ± 158 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
158 ms ± 472 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
2.64 ms ± 104 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

MacBook Air 计时:

100 loops, best of 3: 6.1 ms per loop
100 loops, best of 3: 12.7 ms per loop
1 loop, best of 3: 335 ms per loop
100 loops, best of 3: 4.7 ms per loop

更新我编写的代码(如果您有改进建议或任何可以提供帮助的库,我们很高兴):

import pandas as pd
import numpy as np
import timeit
import matplotlib.pyplot as plt
from collections import defaultdict

df = pd.DataFrame({
    'h1': np.arange(1,11),
    'h2': np.arange(1,11),
    'h3': np.arange(2000,2010)
})

myfuncs = {
"pd.to_datetime(['-'.join(map(str,i)) for i in zip(df['h3'],df['h2'],df['h1'])])":
    lambda: pd.to_datetime(['-'.join(map(str,i)) for i in zip(df['h3'],df['h2'],df['h1'])]),
"pd.to_datetime(['-'.join(i) for i in df[['h3','h2', 'h1']].values.astype(str)])":
    lambda: pd.to_datetime(['-'.join(i) for i in df[['h3','h2', 'h1']].values.astype(str)]),
"pd.to_datetime(df[['h1','h2','h3']].rename(columns={'h1':'day','h2':'month','h3':'year'}))":
    lambda: pd.to_datetime(df[['h1','h2','h3']].rename(columns={'h1':'day','h2':'month','h3':'year'}))
}

d = defaultdict(dict)
step = 10
cont = True
while cont:
    lendf = len(df); print(lendf)
    for k,v in mycodes.items():
        iters = 1
        t = 0
        while t < 0.2:
            ts = timeit.repeat(v, number=iters, repeat=3)
            t = min(ts)
            iters *= 10
        d[k][lendf] = t/iters
        if t > 2: cont = False
    df = pd.concat([df]*step)

pd.DataFrame(d).plot().legend(loc='upper center', bbox_to_anchor=(0.5, -0.15))
plt.yscale('log'); plt.xscale('log'); plt.ylabel('seconds'); plt.xlabel('df rows')
plt.show()

返回:

【讨论】:

  • 更快:pd.to_datetime(['-'.join(i) for i in df[['h3', 'h2', 'h1']].values.astype(str)]);灵感来自this answer
  • @jpp 不错的链接,但是我没有得到这些结果。它慢了大约 3 倍。以我的时间安排
  • @jpp 你觉得我添加的功能怎么样?
  • @jezrael 实际上这是我正在尝试改进的代码。
  • @jezrael 有意思,很相似。
猜你喜欢
  • 2020-11-17
  • 2018-06-05
  • 1970-01-01
  • 1970-01-01
  • 2019-07-04
  • 1970-01-01
  • 2019-09-05
  • 2017-08-07
  • 1970-01-01
相关资源
最近更新 更多