Pandas - 使用apply设置datetime / Timestamp值

时间:2017-12-08 21:39:24

标签: python pandas

让我们考虑以下数据框:

a=pd.DataFrame(data=list(range(10)))

尝试使用apply创建一个新列: 该列应该包含Timestamp对象

def test(x):
    x["date"]=pd.Timestamp("2017-01-01")
    return x

a.apply(test,axis=1)

但是,这会导致数据框中包含时间戳的.value数字属性:

    0   date
0   0   1483228800000000000
1   1   1483228800000000000
2   2   1483228800000000000
3   3   1483228800000000000
4   4   1483228800000000000
5   5   1483228800000000000
6   6   1483228800000000000
7   7   1483228800000000000
8   8   1483228800000000000
9   9   1483228800000000000

怎么会这样?如何在DataFrame中获取正确的时间戳?

编辑:这里给出了问题的完整代码: 这是为了让回应者理解我并不是想将一个简单形成的日期时间列表设置为新列:

def mae(x):
    entry=x.name[0]
    exit=x.name[1]
    m=d.loc[entry:exit,"close"]
    if x.dir==-1:
        r=(m.sub(m[::-1].cummax()[::-1])).abs().max()
        imax=(m.sub(m[::-1].cummax()[::-1])).idxmin()
    elif x.dir==1:
        r=(m.sub(m[::-1].cummin()[::-1])).abs().max()
        imax=(m.sub(m[::-1].cummin()[::-1])).idxmax()   
    else: r=0
    x['mae']=r*gbp['multiplier']
    x['peak']=imax 
    return x

k=g.head().apply(mae,axis=1)

这需要另外一个数据框和一些存储在数据库中的金融价格数据作为输入 - 因此有点难以发明一个例子,同时它足够简单,人们可以快速抓住它并且足够复杂以证明使用.apply

我认为有一些我不理解的东西/或.apply函数中的错误 - 这就是我想要的输入和帮助。谢谢你们!

2 个答案:

答案 0 :(得分:2)

使用您的代码进行几轮调试并进一步调试到pandas,似乎您可以在代码中进行改进。

您可以在_setitem_with_indexer第387-393行阅读更多详情 并在numpy.concatenate

简而言之,_setitem_with_indexer使用numpy.concatenate作为使用索引器设置新值的一部分。

因为a中的第一列只有整数,而您的新列a['date']正在尝试连接integerpandas.Timestamp(它实际上是{{1} }}), numpy只是拒绝这样做。

表明情况就是这样,我们可以通过以下示例来说明。

<强>设置

numpy.datetime64

<强>试验

import pandas as pd
import numpy as np

s1 = [1]

s2 = np.array([np.datetime64("2017-01-01")])

s3 = [pd.Timestamp("2017-01-01")]

a = pd.DataFrame(data=pd.date_range("01-01-2017", "01-06-2017"))

b = pd.DataFrame(data=["d", "c", "d", "d"])

c = pd.DataFrame(data=list(range(10))) 

def test(x):
    x["date"]=pd.Timestamp("2017-01-01")
    return x

我认为这是a.apply(test, axis=1) # output 0 date 0 2017-01-01 2017-01-01 1 2017-01-02 2017-01-01 2 2017-01-03 2017-01-01 3 2017-01-04 2017-01-01 4 2017-01-05 2017-01-01 5 2017-01-06 2017-01-01 b.apply(test, axis=1) # output 0 date 0 d 1483228800000000000 1 c 1483228800000000000 2 d 1483228800000000000 3 d 1483228800000000000 c.apply(test,axis=1) # output 0 date 0 0 1483228800000000000 1 1 1483228800000000000 2 2 1483228800000000000 3 3 1483228800000000000 4 4 1483228800000000000 5 5 1483228800000000000 6 6 1483228800000000000 7 7 1483228800000000000 8 8 1483228800000000000 9 9 1483228800000000000 的更多行为。如果我们选择 使用pd.Timestamp我们将观察到不同的行为,这基本上会在连接中成功;但与numpy.datetime64不一样,这是numpy.concatenate中使用的内容。

<强>观察

_setitem_with_indexer

至于清洁或优雅,我认为温的评论已经非常小,但你可能有理由使用np.concatenate([s1,s2]) # output Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: invalid type promotion invalid type promotion np.concatenate([s1,s3]) # output array([1, Timestamp('2017-01-01 00:00:00')], dtype=object) ***please note here dtype is object***

需要指出的另一件事是,apply接受一个在每个列/行上执行某项操作的函数,但似乎您尝试将函数arg用作DataFrame。

答案 1 :(得分:0)

我认为您只需告知Pandas该列应解释为Datetime

a = pd.DataFrame(data=list(range(10)))
def test(x):
    x['date'] = pd.Timestamp('2017-01-01')
    return x

a = a.apply(test, axis=1)
a.date = a.date.astype('datetime64[ns]')

这给出了:

    0   date
0   0   2017-01-01
1   1   2017-01-01
2   2   2017-01-01
3   3   2017-01-01
4   4   2017-01-01
5   5   2017-01-01
6   6   2017-01-01
7   7   2017-01-01
8   8   2017-01-01
9   9   2017-01-01

或者,我可以通过先创建列并设置其类型来完成此操作:

a = pd.DataFrame(data=list(range(10)))
a['date'] = None
a.date.astype('datetime64[ns]')

def test(x):
    x['date'] = pd.Timestamp('2017-01-01')
    return x

a = a.apply(test, axis=1)