【问题标题】:Arithmetic with pandas objects用 pandas 对象进行算术运算
【发布时间】:2014-10-02 01:19:29
【问题描述】:

我想用 Python 计算两个 Pandas 系列之间的差异。不幸的是,返回了一个我无法理解的错误。我的代码的相关部分是:

import urllib.request 
import pandas as pd 

base_url = "http://ichart.finance.yahoo.com/table.csv?s="

def get_data(base_url,ticker):
    url = base_url + ticker
    source = urllib.request.urlopen(url)
    return  pd.read_csv(source,index_col=0,parse_dates=True,header=None)

ticker_list = {'INTC': 'Intel'}

for ticker in ticker_list:
    prices = get_data(base_url,ticker)
    prices.columns = 'Open','High','Low','Close','Volume','Adj Close'
    closing_prices = prices['Close']
    begin = closing_prices.ix[['2013-01-03']]
    end = closing_prices.ix[['2013-12-27']]
    difference = end.sub(begin)

Python 返回以下错误:

 TypeError: unsupported operand type(s) for -: 'str' and 'str'

但是,type(begin)type(end) 一样返回 pandas.core.series.Series。我使用了end.sub() 的方法,因为我认为我想遵守此处所述的说明:http://pandas.pydata.org/pandas-docs/dev/generated/pandas.Series.sub.html。为了解决我的问题,我(除其他外)遵循了以下建议:Subtract a column from one pandas dataframe from another 无济于事。

您知道错误隐藏在我的代码中的什么地方吗?特别是,为什么 Python 声明我尝试减去字符串?我很感激任何帮助!

更新:在@EdChum 的评论之后,我想发布一些数据:输入begin 给出:

`2013-01-03    21.32
 Name: Close, dtype: object

closing_prices.head() 给出:

`0
Date          Close
2014-08-07    32.68 
2014-08-06    32.85
2014-08-05    32.82
2014-08-04    34.05
Name: Close, dtype: object` 

【问题讨论】:

  • Series 中的值的数据类型是什么(beginend)?试试begin.dtype(或者直接打印系列)
  • begin.dtype 返回dtype('O')
  • df.info()df.dtypes
  • 你必须转换它们,不确定convert_objects是否可以处理这个,否则你必须像df['col'] = df['col'].apply(lambda x: float(x[0]))这样的东西
  • 您必须发布一些数据,这里的问题是您的数据不是整数、浮点数或日期时间,因此减法没有什么意义。我已经发布了各种将 dtype 转换为 datetime 或 floats 的方法,因此您应该能够解决此问题。目前我很难重现您的错误,您需要打印一些数据并查看 dtypes 并修复它们

标签: python string pandas


【解决方案1】:

我不得不将 urllib 更改为 urllib2,并将 urllib.request.urlopen 更改为 urllib2.urlopen.. 但是,它应该是相同的。第一个问题是由将列名存储为值引起的。消除 header=None 可以解决这个问题。

这应该会给你指定的第一个和最后一个日期之间的差异:

import urllib2
import pandas as pd 

base_url = "http://ichart.finance.yahoo.com/table.csv?s="

def get_data(base_url,ticker):
    url = base_url + ticker
    source = urllib2.urlopen(url)
    return  pd.read_csv(source,index_col=0,parse_dates=True)

ticker_list = {'INTC': 'Intel'}

编辑-一定要检查数据的排序。它把最新的放在顶部,最旧的放在底部。

for ticker in ticker_list:
    prices = get_data(base_url,ticker)
    prices.columns = 'Open','High','Low','Close','Volume','Adj Close'
    closing_prices = prices['Close']
    closing_prices = closing_prices['2013-01-03':'2013-12-27']
    difference = closing_prices['2013-12-27'].values - closing_prices['2013-01-03'].values
    print difference

【讨论】:

  • 谢谢!您的方法有效(除了更改print(difference)。但我想知道series.sub() 方法有什么问题。您知道为什么closing_prices['2013-12-27'].values - closing_prices['2013-01-03'].values 有效而difference = end.sub(begin) 无效吗?
  • 我认为子功能需要一个匹配的索引。意思是,如果您想从高点中减去低点(每个都是不同的系列),并排列确切的日期。在您的情况下,索引将不匹配,因为它们是不同的两天。不过,我很可能是错的..
【解决方案2】:

这听起来比实际上要复杂:您需要将end end begin 转换为数字数据类型。试试DataFrame.convert_objects

...
begin = begin.convert_objects(convert_numeric=True)
end = end.convert_objects(convert_numeric=True)
difference = end.sub(begin)

更新:以下代码适用于我:

import urllib2
import pandas as pd 

base_url = "http://ichart.finance.yahoo.com/table.csv?s="

def get_data(base_url,ticker):
    url = base_url + ticker
    source = urllib2.urlopen(url)
    return  pd.read_csv(source,index_col=0,parse_dates=True,header=None)

ticker_list = {'INTC': 'Intel'}

for ticker in ticker_list:
    prices = get_data(base_url,ticker)
    prices.columns = 'Open','High','Low','Close','Volume','Adj Close'

    # this will convert the closing_prices Series to float
    closing_prices = prices['Close'].convert_objects(convert_numeric=True)

    # changed the double square brackets [[]] to single square brackets to
    # obtain a scalar, rather than a single element Series
    begin = closing_prices.ix['2013-01-03']
    end = closing_prices.ix['2013-12-27']
    difference = end - begin

【讨论】:

  • 感谢您的回复。根据您的建议 difference = end.sub(begin) 仍然返回相同的 NaN 错误。但是,使用end.values - begin.values 给了我正确的解决方案。你知道为什么sub() 方法不起作用吗?我认为这是 Pandas 指示我们做的事情。
  • 你的问题,我最初没有意识到,是你试图减去两个标量,而不是两个向量。 sub 方法要求两个Series 对齐(即索引相同)。我已经更新了我的答案以更好地解释这一点。
猜你喜欢
  • 1970-01-01
  • 2021-11-02
  • 1970-01-01
  • 1970-01-01
  • 2016-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多