【问题标题】:manipulating value of pandas dataframe cell based on value in previous row without iteration根据前一行中的值操作熊猫数据框单元格的值而无需迭代
【发布时间】:2016-04-08 13:31:31
【问题描述】:

我有一个从 Google Finance 编译的具有约 3900 行和 6 列的 pandas 数据框。其中一列以 unix 格式定义时间,特别是定义市场交易日的时间。在这种情况下,道指从 930A EST 到 4P EST。但是,只有每天开始的单元格 (930A) 具有完整的 unix 时间戳(以“a”为前缀),其他是一天中第一次之后的分钟数。

以下是原始数据的示例:

          Date   Close    High     Low    Open  Volume
0  a1450449000  173.87  173.87  173.83  173.87   46987
1            1  173.61  173.83  173.55  173.78   19275
2            2  173.37  173.63  173.37  173.60   16014
3            3  173.50  173.59  173.31  173.34   14198
4            4  173.50  173.57  173.46  173.52    7010
          Date   Close    High     Low    Open  Volume
388          388  171.16  171.27  171.15  171.26   11809
389          389  171.11  171.23  171.07  171.18   30449
390          390  170.89  171.16  170.89  171.09  163937
391  a1450708200  172.28  172.28  172.28  172.28   23880
392            1  172.27  172.27  172.00  172.06    2719

索引 391 处的更改不是连续的,因此像 @Stefan 这样的解决方案很遗憾无法正确调整 Date 值。

我可以很容易地使用 lambda 并逐行删除“a”(如有必要)将值转换为整数,并使用以下代码将超过 930A 的分钟转换为秒:

import pandas as pd
import numpy as np
import datetime

bars = pd.read_csv(r'http://www.google.com/finance/getprices?i=60&p=10d&f=d,o,h,l,c,v&df=cpct&q=DIA', skiprows=7, header=None, names=['Date', 'Close', 'High', 'Low', 'Open', 'Volume'])

bars['Date'] = bars['Date'].map(lambda x: int(x[1:]) if x[0] == 'a' else int(x))    
bars['Date'] = bars['Date'].map(lambda u: u * 60 if u < 400 else u)

现在我想做的是,在不迭代数据帧的情况下,确定 bar['Date'] 的值是否不是 unix 时间戳(例如,在此数据集的条款中

我知道我可以通过以下方式比较上一行:

bars['Date'][:-1]>bars['Date'][1:]

我觉得这将是要走的路,但我想不出在函数中使用它的方法,因为它返回一个系列。

提前感谢您的帮助!

【问题讨论】:

    标签: python numpy pandas quantitative-finance


    【解决方案1】:

    您可以添加一个始终包含最新Timestamp 的新列,然后在必要时添加到Date

    threshold = 24000
    bars['Timestamp'] = bars[bars['Date']>threshold].loc[:, 'Date']
    bars['Timestamp'] = bars['Timestamp'].fillna(method='ffill')
    bars['Date'] = bars.apply(lambda x: x.Date + x.Timestamp if x.Date < threshold else x.Date, axis=1)
    bars.drop('Timestamp', axis=1, inplace=True)
    

    得到:

                Date   Close     High     Low    Open  Volume
    0     1450449000  173.87  173.870  173.83  173.87   46987
    1     1450449060  173.61  173.830  173.55  173.78   19275
    2     1450449120  173.37  173.630  173.37  173.60   16014
    3     1450449180  173.50  173.590  173.31  173.34   14198
    4     1450449240  173.50  173.570  173.46  173.52    7010
    5     1450449300  173.66  173.680  173.44  173.45   10597
    6     1450449360  173.40  173.670  173.34  173.67   14270
    7     1450449420  173.36  173.360  173.13  173.32   22485
    8     1450449480  173.29  173.480  173.25  173.36   18542
    

    【讨论】:

    • 如果日期列是连续的,这将是一个可接受的解决方案。也许我的问题不够清楚。在大约(某些数据偶尔丢失)索引 390 处,'Date' 列重置为新的日期值,此时'Timespamp' 列将打印正确的值,但不会将'timestamp ='重置为这个新的日期值所有后续行都将不正确。我将修改我的问题以显示一个示例。
    • 由于我对这一切还是个新手,我确实有一个问题是由于尝试实现与您之前类似的答案而产生的。如果我是正确的,你不能在 lambda 中分配值,就像 (lambda x: x + timestamp if x &lt; threshold else x = timestamp) 说的那样,这将解决这个问题。有没有类似的东西可以达到同样的目的?
    • 太棒了。我没有意识到我可以以这种方式使用 Dataframe.loc[] 。谢谢!
    猜你喜欢
    • 2018-06-22
    • 2016-04-22
    • 1970-01-01
    • 2021-11-23
    • 2021-08-01
    • 2020-10-02
    • 1970-01-01
    • 2014-06-02
    • 2021-08-07
    相关资源
    最近更新 更多