以下链接包含美国联邦储备银行发布的一些数据: http://www.federalreserve.gov/monetarypolicy/fomcprojtabl20150318.htm
我将该链接上的最后一个表复制并粘贴到LibreOffice Calc中的电子表格中(为了清楚起见,该表称为“适当的政策紧缩速度:目标范围的中点或联邦基金利率的目标水平”)
现在,我想要做的就是将该表读入numpy数组或python列表或其他内容,并能够对该表执行一些基本的描述性统计。请注意,该表有“空位”,其中很多都是。
这是我将电子表格保存为fomc.csv之后运行的内容:
data = []
f = open('fomc.csv', 'rt')
reader = csv.reader(f)
for row in reader:
data.append(row)
data
我得到奇怪的东西(很多'\ xc2 \ xa0'):
[['Midpoint of target range\nor target level (Percent)',
'2015',
'2016',
'2017',
'Longer Run'],
['0.125', '2', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0'],
['0.25', '', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0'],
['0.375', '1', '1', '\xc2\xa0', '\xc2\xa0'],
['0.5', '', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0'],
['0.625', '7', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0'],
['0.75', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0'],
['0.875', '3', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0'],
['1', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0'],
['1.125', '1', '1', '\xc2\xa0', '\xc2\xa0'],
['1.25', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0'],
['1.375', '2', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0'],
['1.5', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0'],
['1.625', '1', '6', '\xc2\xa0', '\xc2\xa0'],
['1.75', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0'],
['1.875', '\xc2\xa0', '3', '\xc2\xa0', '\xc2\xa0'],
['2', '\xc2\xa0', '\xc2\xa0', '1', '\xc2\xa0'],
['2.125', '\xc2\xa0', '1', '\xc2\xa0', '\xc2\xa0'],
['2.25', '\xc2\xa0', '1', '\xc2\xa0', '\xc2\xa0'],
['2.375', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0'],
['2.5', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0'],
['2.625', '\xc2\xa0', '1', '3', '\xc2\xa0'],
['2.75', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0'],
['2.875', '\xc2\xa0', '\xc2\xa0', '2', '\xc2\xa0'],
['3', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0', '1'],
['3.125', '\xc2\xa0', '\xc2\xa0', '4', '\xc2\xa0'],
['3.25', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0'],
['3.375', '\xc2\xa0', '2', '1', '\xc2\xa0'],
['3.5', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0', '7'],
['3.625', '\xc2\xa0', '\xc2\xa0', '2', '\xc2\xa0'],
['3.75', '\xc2\xa0', '1', '2', '6'],
['3.875', '\xc2\xa0', '\xc2\xa0', '1', '\xc2\xa0'],
['4', '\xc2\xa0', '\xc2\xa0', '1', '2'],
['4.125', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0'],
['4.25', '\xc2\xa0', '\xc2\xa0', '\xc2\xa0', '1']]
所以,问题:
a)获取所有这些'\ xc2 \ xa0'字符串是否正常?
b)我应该用其他值替换它们,例如''或'0',使用(即,这是一种聪明的方法吗?):
data = np.array([[el.replace('\xc2\xa0',' ') for el in row] for row in data])
c)将应该是浮点值但是字符串的数据转换为浮点值的最佳方法是什么?我需要遍历np.array吗?
考虑到第一栏,我希望能够做到像
这样的事情data.T[0][1:] = [float(el) for el in data.T[0][1:]]
但这不起作用,因为你不能以这种方式改变数组的切片。
答案 0 :(得分:2)
a)如果您没有使用相同的编码来读取文件,那么获取错误字符是正常的。文件只是字节,它们可以根据编码进行不同的解释。 "古怪"符号几乎总是意味着你使用了错误的解释"。
b)打开文本文件时,应始终指定其编码。 Python3强迫你这样做。在Python2中你可以这样做:
from io import open
with open('fomc.csv', 'r', encoding='utf-8') as f:
reader = csv.reader(f)
我尝试了你的例子并且无法重现同样的错误。我的列表中包含空单元格的空字符串。因为你必须用合理的默认值(例如0)替换它们,无论如何都可以。
c)您应该从csv complete中清理您的输入,然后将其传递给numpy。
你总是可以为它编写一个函数:
def sanitize_cell_content(cell_content):
try:
return float(cell_content)
except ValueError:
return 0.0
sanitized_data = [[sanitize_cell_content(el) for el in row] for row in data]
更正:正如nhawke指出的那样,假设csv在两个Python版本中都处理unicode,我犯了一个错误。在Python2中不是这种情况。即使你正确地阅读了文件,它也会爆炸。
然而,好消息是csv不是一种非常复杂的格式,所以你通常不需要csv.reader
来使用它。使用unicode字符读取csv文件并将其转换为行列表就像
with open('fomc.csv', 'r', encoding='utf-8') as f:
data = [line.split(',') for line in f.readlines()]
从那里你可以消毒细胞并按上图所示继续进行。
答案 1 :(得分:2)
a)是的,这是正常的。您正在将UTF8编码的HTML内容粘贴到Calc中。该内容包括一个UTF8编码的NO-BREAK SPACE unicode字符,用于表格的空列。
>>> s = '\xc2\xa0' # UTF8 encoded string
>>> s.decode('utf8')
u'\xa0'
>>> import unicodedata
>>> print unicodedata.name(s.decode('utf8')) # decode to unicode and lookup name
NO-BREAK SPACE
看起来你使用"普通"将表粘贴到Calc中。糊。如果您使用" Paste Special"将数据粘贴到Calc中。并选择为"无格式文本"你最终会得到ASCII空格而不是非空格。此外,保存文件时,您可以指定要使用的编码。选择UTF8或ASCII,因为该表中没有任何Unicode字符,因此两者都是相同的。
b)如果您决定将未格式化的文本粘贴到Calc中,那么您可以像这样处理文件:
import csv
with open('fomc.csv') as infile:
data= []
for row in csv.reader(infile):
data.append([float(field.strip()) if field.strip() else None for field in row])
data
将包含:
[[0.125, 2.0, None, None, None], [0.25, None, None, None, None], ..., [4.25, None, None, None, 1.0]]
我已使用None
来表示空列。您可以使用0或''如你所愿。另外,我没有复制&将列标题粘贴到CSV文件中,因此我不必担心它们。
c)参见b) - 在读取文件时对所有非空字符串执行了浮点转换。