在Python / Pandas中计算两行之间的差异

84

在Python中,我如何引用先前的行并对其进行计算?具体而言,我正在使用pandas中的dataframes - 我有一个包含股票价格信息的数据框,看起来像这样:

           Date   Close  Adj Close
251  2011-01-03  147.48     143.25
250  2011-01-04  147.64     143.41
249  2011-01-05  147.05     142.83
248  2011-01-06  148.66     144.40
247  2011-01-07  147.93     143.69

以下是我如何创建这个数据框:

import pandas

url = 'http://ichart.finance.yahoo.com/table.csv?s=IBM&a=00&b=1&c=2011&d=11&e=31&f=2011&g=d&ignore=.csv'
data = data = pandas.read_csv(url)

## now I sorted the data frame ascending by date 
data = data.sort(columns='Date')

从第2行开始计算,或者在这种情况下,我猜是250(附言-那是索引吗?),我想为此数据框中的每个条目计算2011-01-03和2011-01-04之间的差异。我相信适当的方法是编写一个函数,该函数获取当前行,然后找出前一行,并计算它们之间的差异,使用 pandasapply 函数更新数据帧的值。

这样做对吗?如果是,则应该使用索引来确定差异吗?(注意-我仍处于初学python模式中,因此索引可能不是正确的术语,也可能不是实现此目的的正确方式)


仅仅找到两个日期的行并计算它们之间的差异不就足够了吗? - redShadow
@redShadow 有趣的想法。我之前没有这样想过。我唯一看到的问题是如何处理周末?交易日只有252天,而不是365天。如果你试图向上加1天,而那天是周末,函数将失败。虽然,我猜你可以在函数中加入一些错误处理... - mikebmassey
不,等一下..你到底想要实现什么?对于数据集中的所有记录,计算每天与前一天的差异..? - redShadow
@redShadow 没错。逐行比较,与前一天的差异。第一行将为0,因此我需要想出一些错误处理方法,但是... - mikebmassey
3个回答

130

我认为您想要做这样的事情:

In [26]: data
Out[26]: 
           Date   Close  Adj Close
251  2011-01-03  147.48     143.25
250  2011-01-04  147.64     143.41
249  2011-01-05  147.05     142.83
248  2011-01-06  148.66     144.40
247  2011-01-07  147.93     143.69

In [27]: data.set_index('Date').diff()
Out[27]: 
            Close  Adj Close
Date                        
2011-01-03    NaN        NaN
2011-01-04   0.16       0.16
2011-01-05  -0.59      -0.58
2011-01-06   1.61       1.57
2011-01-07  -0.73      -0.71

4
好的,您想知道如何将这个内容添加为数据表中的新列? - greenafrican
@Chang She,如果我不想要差异而是实际值怎么办?例如,是否有像value(1)或value(1:3).mean()这样的东西。第二个虚构的例子将获得下一个、第二个和第三个值的平均值。那会很有用。 - IcemanBerlin
1
在pandas中,.shift()函数可以返回值。 - Sean W.
感谢您的回答。对于那些想要n天差异的人,值得一提的是,您可以将输入参数“periods”设置为n。有关更多详细信息,请查看“pandas.DataFrame.diff”文档:http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.diff.html。 - JejeBelfort
1
回答 greenafrica 的后续问题。你可以使用 pd.concat 将原始数据和新的差异数据合并在一起,例如:pd.concat([data,data[['Close', 'Adj Close']].diff().rename({'Close':'Close Diff', 'Adj Close':'Adj Close Diff'}, axis=1)], axis=1) - Uwe Mayer
1
如果你想把差异保存到另一列中,可以这样做: df['close_diff'] = df['Close'].diff() - Save

28

计算一列的差异。您可以按照以下步骤进行。

df=
      A      B
0     10     56
1     45     48
2     26     48
3     32     65

我们想要计算A中仅有的行差异,并且只考虑那些小于15的行。

df['A_dif'] = df['A'].diff()
df=
          A      B      A_dif
    0     10     56      Nan
    1     45     48      35
    2     26     48      19
    3     32     65      6
df = df[df['A_dif']<15]

df=
          A      B      A_dif
    0     10     56      Nan
    3     32     65      6

1

我不了解pandas,但我相信它对此有特定的解决方案;然而,我会给你提供纯Python的解决方案,即使你需要使用pandas,这也可能会有所帮助:

import csv
import urllib

# This basically retrieves the CSV files and loads it in a list, converting
# All numeric values to floats
url='http://ichart.finance.yahoo.com/table.csv?s=IBM&a=00&b=1&c=2011&d=11&e=31&f=2011&g=d&ignore=.csv'
reader = csv.reader(urllib.urlopen(url), delimiter=',')
# We sort the output list so the records are ordered by date
cleaned = sorted([[r[0]] + map(float, r[1:]) for r in list(reader)[1:]])

for i, row in enumerate(cleaned):  # enumerate() yields two-tuples: (<id>, <item>)
    # The try..except here is to skip the IndexError for line 0
    try:
        # This will calculate difference of each numeric field with the same field
        # in the row before this one
        print row[0], [(row[j] - cleaned[i-1][j]) for j in range(1, 7)]
    except IndexError:
        pass

5
之所以对此进行负面评价,是因为除了模仿pandas的功能之外,还使用了嵌套的for循环,这在Python中速度较慢。而Pandas则可以在C级别上执行此操作。 - jonathanrocher
7
因为原始问题的标签为“pandas”,这直接指向了作者解决问题的方法,所以进行了负投票。 - ruX
2
有时候你不知道自己想要什么,直到它被呈现给你 :) - ilyas
标题写着“Python / Pandas”。这可能会让人产生误解,至少是回答的一个原因。更好的写法应该是“Python pandas”或“pandas(Python)”。 - questionto42

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接