版本 0.12.0 (2013年7月24日)#
这是从 0.11.0 版本以来的一个重大发布,包括几个新功能和增强功能,以及大量错误修复。
亮点包括一致的 I/O API 命名方案、读取 html 的例程、将 MultiIndexes 写入 csv 文件、读取和写入 STATA 数据文件、读取和写入 JSON 格式文件、Python 3 支持 HDFStore
、通过 filter
过滤 groupby 表达式,以及一个重新设计的 replace
例程,该例程接受正则表达式。
API 变化#
I/O API 现在与一组顶级
reader
函数更加一致,这些函数可以通过pd.read_csv()
访问,通常返回一个pandas
对象。
read_csv
read_excel
read_hdf
read_sql
read_json
read_html
read_stata
read_clipboard
相应的
writer
函数是对象方法,可以通过df.to_csv()
访问
to_csv
to_excel
to_hdf
to_sql
to_json
to_html
to_stata
to_clipboard
修复了 Series 和 DataFrames 上的模数和整数除法,使其与
float
数据类型一样,在适当的情况下返回np.nan
或np.inf
(GH 3590)。这纠正了 numpy 将integer
和float
数据类型区别对待的错误。In [1]: p = pd.DataFrame({"first": [4, 5, 8], "second": [0, 0, 3]}) In [2]: p % 0 Out[2]: first second 0 NaN NaN 1 NaN NaN 2 NaN NaN In [3]: p % p Out[3]: first second 0 0.0 NaN 1 0.0 NaN 2 0.0 0.0 In [4]: p / p Out[4]: first second 0 1.0 NaN 1 1.0 NaN 2 1.0 1.0 In [5]: p / 0 Out[5]: first second 0 inf NaN 1 inf NaN 2 inf inf在
groupby
中添加squeeze
关键字,以允许在组唯一时从 DataFrame 缩减到 Series。这是从 0.10.1 版本回归的。我们正在恢复到之前的行为。这意味着无论组是否唯一,groupby 都将返回相同形状的对象。恢复此问题 (GH 2893) 与 (GH 3596)。In [2]: df2 = pd.DataFrame([{"val1": 1, "val2": 20}, ...: {"val1": 1, "val2": 19}, ...: {"val1": 1, "val2": 27}, ...: {"val1": 1, "val2": 12}]) In [3]: def func(dataf): ...: return dataf["val2"] - dataf["val2"].mean() ...: In [4]: # squeezing the result frame to a series (because we have unique groups) ...: df2.groupby("val1", squeeze=True).apply(func) Out[4]: 0 0.5 1 -0.5 2 7.5 3 -7.5 Name: 1, dtype: float64 In [5]: # no squeezing (the default, and behavior in 0.10.1) ...: df2.groupby("val1").apply(func) Out[5]: val2 0 1 2 3 val1 1 0.5 -0.5 7.5 -7.5当使用基于标签的索引器掩码(例如布尔序列)进行布尔索引时,即使带有整数标签,也会在
iloc
上引发。由于iloc
纯粹是基于位置的,序列上的标签无法对齐 (GH 3631)这种情况很少使用,而且有很多替代方案。这保留了
iloc
API 使其 纯粹 基于位置。In [6]: df = pd.DataFrame(range(5), index=list("ABCDE"), columns=["a"]) In [7]: mask = df.a % 2 == 0 In [8]: mask Out[8]: A True B False C True D False E True Name: a, dtype: bool # this is what you should use In [9]: df.loc[mask] Out[9]: a A 0 C 2 E 4 # this will work as well In [10]: df.iloc[mask.values] Out[10]: a A 0 C 2 E 4
df.iloc[mask]
将引发一个ValueError
绘图函数的
raise_on_error
参数已被移除。取而代之的是,当对象的dtype
为object
时,绘图函数会引发TypeError
,以提醒您尽量避免使用object
数组,因此如果您需要绘制某些内容,应将其转换为适当的数值类型。在 DataFrame 绘图方法中添加
colormap
关键字。接受一个 matplotlib 颜色映射对象(例如,matplotlib.cm.jet)或该对象的字符串名称(例如,’jet’)。颜色映射被采样以选择每列的颜色。请参阅 颜色映射 获取更多信息。(GH 3860)
DataFrame.interpolate()
现在已被弃用。请改用DataFrame.fillna()
和DataFrame.replace()
。(GH 3582, GH 3675, GH 3676)
DataFrame.replace()
的method
和axis
参数已被弃用
DataFrame.replace
的infer_types
参数已被移除,现在默认进行转换。(GH 3907)在
DataFrame.insert
中添加关键字allow_duplicates
,如果为True
,则允许插入重复列,默认值为False
(与 0.12 之前的版本相同) (GH 3679)IO api
添加了顶级函数
read_excel
以替代以下内容,原始 API 已弃用,并将在未来版本中移除from pandas.io.parsers import ExcelFile xls = ExcelFile("path_to_file.xls") xls.parse("Sheet1", index_col=None, na_values=["NA"])与
import pandas as pd pd.read_excel("path_to_file.xls", "Sheet1", index_col=None, na_values=["NA"])添加了顶级函数
read_sql
,它等同于以下内容from pandas.io.sql import read_frame read_frame(...)
DataFrame.to_html
和DataFrame.to_latex
现在接受它们第一个参数的路径 (GH 3702)不允许对
datetime64[ns]
进行 astype 转换,除非转换为object
,以及timedelta64[ns]
转换为object/int
(GH 3425)
datetime64
数据类型的行为在某些所谓的归约操作(GH 3726)方面已经改变。以下操作在Series
上执行时现在会引发TypeError
,在DataFrame
上执行时会返回一个 空的Series
,类似于在这些操作在例如slice
对象的DataFrame
上执行:
sum, prod, mean, std, var, skew, kurt, corr, 和 cov
read_html
在读取时现在默认为None
,并且在 lxml 解析失败时回退到bs4
+html5lib
。尝试直到成功的解析器列表也是有效的。内部
pandas
类层次结构已经发生了变化(略有变化)。之前的PandasObject
现在被称为PandasContainer
,一个新的PandasObject
已经成为PandasContainer
以及Index
、Categorical
、GroupBy
、SparseList
和SparseArray
(以及它们的基类)的基类。目前,PandasObject
提供了字符串方法(来自StringMixin
)。 (GH 4090, GH 4092)新的
StringMixin
,给定一个__unicode__
方法,可以获得兼容 python 2 和 python 3 的字符串方法(__str__
、__bytes__
和__repr__
)。并确保整个过程中的字符串安全性。现在在 pandas 库的许多地方都有应用。(GH 4090, GH 4092)
IO 增强#
pd.read_html()
现在可以解析 HTML 字符串、文件或 URL 并返回 DataFrame,感谢 @cpcloud。(GH 3477, GH 3605, GH 3606, GH 3616)。它使用一个 单一 解析器后端:BeautifulSoup4 + html5lib 查看文档你可以使用
pd.read_html()
来读取DataFrame.to_html()
的输出,如下所示In [11]: import io In [12]: df = pd.DataFrame({"a": range(3), "b": list("abc")}) In [13]: print(df) a b 0 0 a 1 1 b 2 2 c In [14]: html = df.to_html() In [15]: alist = pd.read_html(io.StringIO(html), index_col=0) In [16]: print(df == alist[0]) a b 0 True True 1 True True 2 True True注意,这里的
alist
是一个 Python列表
,因此pd.read_html()
和DataFrame.to_html()
不是互逆的。
pd.read_html()
不再对日期字符串进行硬转换 (GH 3656)。警告
你可能需要安装一个较旧版本的 BeautifulSoup4,查看安装文档
添加了用于读写 Stata 文件的模块:
pandas.io.stata
(GH 1512) 可通过read_stata
顶级函数进行读取,以及通过to_stata
DataFrame 方法进行写入,查看文档添加了用于读写json格式文件的模块:
pandas.io.json
可通过read_json
顶级函数进行读取,以及to_json
DataFrame 方法进行写入,查看文档 各种问题 (GH 1226, GH 3804, GH 3876, GH 3867, GH 1305)
MultiIndex
列支持读取和写入 csv 格式文件
read_csv
中的header
选项现在接受一个包含要读取索引的行列表。选项
tupleize_cols
现在可以在to_csv
和read_csv
中指定,以提供与 0.12 版本之前的行为的兼容性,即通过元组列表写入和读取MultIndex
列。0.12 版本的默认设置是写入元组列表,并且不将元组列表解释为MultiIndex
列。注意:0.12 版本中的默认行为与之前的版本保持不变,但从 0.13 开始,默认的 写入和读取
MultiIndex
列将以新格式进行。(GH 3571, GH 1651, GH 3141)如果未指定
index_col``(例如,你没有索引,或者使用 ``df.to_csv(..., index=False
编写),那么列索引上的任何names
都将 丢失。In [17]: mi_idx = pd.MultiIndex.from_arrays([[1, 2, 3, 4], list("abcd")], names=list("ab")) In [18]: mi_col = pd.MultiIndex.from_arrays([[1, 2], list("ab")], names=list("cd")) In [19]: df = pd.DataFrame(np.ones((4, 2)), index=mi_idx, columns=mi_col) In [20]: df.to_csv("mi.csv") In [21]: print(open("mi.csv").read()) c,,1,2 d,,a,b a,b,, 1,a,1.0,1.0 2,b,1.0,1.0 3,c,1.0,1.0 4,d,1.0,1.0 In [22]: pd.read_csv("mi.csv", header=[0, 1, 2, 3], index_col=[0, 1]) Out[22]: c 1 2 d a b a Unnamed: 2_level_2 Unnamed: 3_level_2 1 1.0 1.0 2 b 1.0 1.0 3 c 1.0 1.0 4 d 1.0 1.0在 Python3 上对
HDFStore
的支持(通过PyTables 3.0.0
)通过
read_hdf
支持迭代器,当迭代完成时自动打开和关闭存储。这仅适用于 表格In [25]: path = 'store_iterator.h5' In [26]: pd.DataFrame(np.random.randn(10, 2)).to_hdf(path, 'df', table=True) In [27]: for df in pd.read_hdf(path, 'df', chunksize=3): ....: print(df) ....: 0 1 0 0.713216 -0.778461 1 -0.661062 0.862877 2 0.344342 0.149565 0 1 3 -0.626968 -0.875772 4 -0.930687 -0.218983 5 0.949965 -0.442354 0 1 6 -0.402985 1.111358 7 -0.241527 -0.670477 8 0.049355 0.632633 0 1 9 -1.502767 -1.225492
read_csv
现在会在文件不包含任何列时抛出一个更详细的信息错误消息,例如,所有字符都是换行符。
其他增强功能#
DataFrame.replace()
现在允许在包含对象数据类型的Series
上使用正则表达式。请参阅常规文档中的示例部分 通过字符串表达式替换例如,你可以这样做
In [23]: df = pd.DataFrame({"a": list("ab.."), "b": [1, 2, 3, 4]}) In [24]: df.replace(regex=r"\s*\.\s*", value=np.nan) Out[24]: a b 0 a 1 1 b 2 2 NaN 3 3 NaN 4将字符串
'.'
的所有出现替换为零个或多个周围空白字符的NaN
。常规的字符串替换仍然按预期工作。例如,你可以这样做
In [25]: df.replace(".", np.nan) Out[25]: a b 0 a 1 1 b 2 2 NaN 3 3 NaN 4将字符串
'.'
的所有出现替换为NaN
。
pd.melt()
现在接受可选参数var_name
和value_name
来指定返回的 DataFrame 的自定义列名。
pd.set_option()
现在允许 N 个选项、值对 (GH 3667)。假设我们有一个选项
'a.b'
和另一个选项'b.c'
。我们可以同时设置它们:In [31]: pd.get_option('a.b') Out[31]: 2 In [32]: pd.get_option('b.c') Out[32]: 3 In [33]: pd.set_option('a.b', 1, 'b.c', 4) In [34]: pd.get_option('a.b') Out[34]: 1 In [35]: pd.get_option('b.c') Out[35]: 4对于组对象的
filter
方法返回原始对象的一个子集。假设我们只想取那些属于组总和大于2的组的元素。In [26]: sf = pd.Series([1, 1, 2, 3, 3, 3]) In [27]: sf.groupby(sf).filter(lambda x: x.sum() > 2) Out[27]: 3 3 4 3 5 3 dtype: int64
filter
的参数必须是一个函数,该函数应用于整个组时,返回True
或False
。另一个有用的操作是过滤掉属于只有少数成员的组的元素。
In [28]: dff = pd.DataFrame({"A": np.arange(8), "B": list("aabbbbcc")}) In [29]: dff.groupby("B").filter(lambda x: len(x) > 2) Out[29]: A B 2 2 b 3 3 b 4 4 b 5 5 b或者,我们可以返回一个类似索引的对象,而不是丢弃违规的组,其中未通过过滤器的组用 NaNs 填充。
In [30]: dff.groupby("B").filter(lambda x: len(x) > 2, dropna=False) Out[30]: A B 0 NaN NaN 1 NaN NaN 2 2.0 b 3 3.0 b 4 4.0 b 5 5.0 b 6 NaN NaN 7 NaN NaNSeries 和 DataFrame 的 hist 方法现在接受一个
figsize
参数 (GH 3834)DatetimeIndexes 在连接操作期间不再尝试转换混合整数索引 (GH 3877)
Timestamp.min 和 Timestamp.max 现在表示有效的 Timestamp 实例,而不是默认的 datetime.min 和 datetime.max(分别),感谢 @SleepingPills
read_html
现在在未找到表格且检测到 BeautifulSoup==4.2.0 时会引发 (GH 4214)
实验性功能#
添加了实验性的
CustomBusinessDay
类以支持带有自定义假日日历和自定义周掩码的DateOffsets
。 (GH 2301)备注
这使用了在 Numpy 1.7 中引入的
numpy.busdaycalendar
API,因此需要 Numpy 1.7.0 或更新版本。In [31]: from pandas.tseries.offsets import CustomBusinessDay In [32]: from datetime import datetime # As an interesting example, let's look at Egypt where # a Friday-Saturday weekend is observed. In [33]: weekmask_egypt = "Sun Mon Tue Wed Thu" # They also observe International Workers' Day so let's # add that for a couple of years In [34]: holidays = ["2012-05-01", datetime(2013, 5, 1), np.datetime64("2014-05-01")] In [35]: bday_egypt = CustomBusinessDay(holidays=holidays, weekmask=weekmask_egypt) In [36]: dt = datetime(2013, 4, 30) In [37]: print(dt + 2 * bday_egypt) 2013-05-05 00:00:00 In [38]: dts = pd.date_range(dt, periods=5, freq=bday_egypt) In [39]: print(pd.Series(dts.weekday, dts).map(pd.Series("Mon Tue Wed Thu Fri Sat Sun".split()))) 2013-04-30 Tue 2013-05-02 Thu 2013-05-05 Sun 2013-05-06 Mon 2013-05-07 Tue Freq: C, dtype: object
错误修复#
绘图函数现在会在尝试绘图之前,如果相关对象的 dtype 为
object
,则会引发TypeError
(GH 1818, GH 3572, GH 3911, GH 3912),但它们会尝试将对象数组转换为数值数组(如果可能的话),这样你仍然可以绘制,例如,一个包含浮点数的对象数组。这发生在任何绘图之前,从而消除了任何虚假的绘图出现。
fillna
方法现在如果value
参数是列表或元组,则会引发TypeError
。
Series.str
现在支持迭代 (GH 3638)。你可以迭代Series
中每个字符串的各个元素。每次迭代产生一个Series
,其中每个索引处的元素要么是原始Series
中的单个字符,要么是NaN
。例如,In [38]: strs = "go", "bow", "joe", "slow" In [32]: ds = pd.Series(strs) In [33]: for s in ds.str: ...: print(s) 0 g 1 b 2 j 3 s dtype: object 0 o 1 o 2 o 3 l dtype: object 0 NaN 1 w 2 e 3 o dtype: object 0 NaN 1 NaN 2 NaN 3 w dtype: object In [41]: s Out[41]: 0 NaN 1 NaN 2 NaN 3 w dtype: object In [42]: s.dropna().values.item() == "w" Out[42]: True迭代器产生的最后一个元素将是一个包含最长字符串的最后一个元素的
Series
,其他所有元素都是NaN
。这里因为'slow'
是最长的字符串,并且没有其他字符串具有相同的长度,所以产生的Series
中只有'w'
是非空字符串。
HDFStore
非唯一索引支持已澄清 (GH 3468)。
修复在 DataFrame 中为重复索引分配新索引时会失败的问题 (GH 3468)
修复使用重复索引构建 DataFrame 的问题
ref_locs 支持允许多个数据类型之间的重复索引,允许 iget 支持始终找到索引(即使在不同数据类型之间)(GH 2194)
在具有非唯一索引的 DataFrame 上使用 applymap 现在可以正常工作(移除了警告)(GH 2786),并修复 (GH 3230)
修复 to_csv 以处理非唯一列 (GH 3495)
使用 getitem 的重复索引将按正确顺序返回项目(GH 3455, GH 3457)并处理像唯一索引那样的缺失元素(GH 3561)
使用空的 DataFrame.from_records 重复索引将返回正确的框架 (GH 3562)
当重复项跨越不同数据类型时,连接产生非唯一列的问题已修复 (GH 3602)
允许插入/删除非唯一列 (GH 3679)
通过
loc
和朋友们使用切片进行非唯一索引已修复 (GH 3659)允许插入/删除非唯一列 (GH 3679)
扩展
reindex
以正确处理非唯一索引 (GH 3679)
DataFrame.itertuples()
现在可以处理具有重复列名的数据框 (GH 3873)通过
iloc
进行非唯一索引的错误 (GH 4017);为reindex
添加了takeable
参数以进行基于位置的取值通过
.ix/.loc
和__getitem__
允许在序列中进行非唯一索引 (GH 4246)修复了使用
.ix/.loc
时的非唯一索引内存分配问题 (GH 4280)
DataFrame.from_records
不接受空的 recarrays (GH 3682)
read_html
现在正确地跳过测试 (GH 3741)修复了一个
DataFrame.replace
在to_replace
参数中使用编译的正则表达式时无法正常工作的错误 (GH 3907)改进了
network
测试装饰器以捕获IOError
(因此也包括URLError
)。添加了with_connectivity_check
装饰器,以允许显式检查网站作为判断是否有网络连接的代理。此外,新增了optional_args
装饰器工厂用于装饰器。(GH 3910, GH 3914)修复了打开太多套接字导致连接重置问题的测试问题 (GH 3982, GH 3985, GH 4028, GH 4054)
在 test_yahoo 和 test_google 中修复了失败的测试,其中符号未被检索但被访问 (GH 3982, GH 3985, GH 4028, GH 4054)
Series.hist
现在会从当前环境中获取图形,如果没有传递图形的话。修复了一个 1xN DataFrame 在遇到 1xN 掩码时会出错的问题 (GH 4071)
修复了 sharex 和 sharey 未传递给 grouped_hist 的错误 (GH 4089)
修复了
DataFrame.replace
中的一个错误,当 regex=False 时,嵌套的字典未被迭代 (GH 4115)在使用
to_datetime
中的format
参数时,修复了微秒解析中的错误 (GH 4152)修复了
PandasAutoDateLocator
中invert_xaxis
错误触发了MilliSecondLocator
的 bug (GH 3990)修复了在 matplotlib 1.1.1 中未对无效颜色映射引发错误的绘图问题 (GH 4215)
修复了在
DataFrame.plot(kind='kde')
中显示的图例 (GH 4216)修复了索引切片未携带名称属性的错误 (GH 4226)
在特定时区中使用字符串数组初始化
DatetimeIndex
时修复了错误 (GH 4229)修复了未正确跳过 html5lib 的错误 (GH 4265)
修复了 get_data_famafrench 未使用正确文件边缘的错误 (GH 4281)
请参阅 完整发布说明 或在 GitHub 上的问题跟踪器以获取完整列表。
贡献者#
总共有50人为此版本贡献了补丁。名字后面带有“+”的人首次贡献了补丁。
Andy Hayden
Chang She
Christopher Whelan
Damien Garaud
Dan Allan
Dan Birken
Dieter Vandenbussche
Dražen Lučanin
Gábor Lipták +
Jeff Mellen +
Jeff Tratner +
Jeffrey Tratner +
Jonathan deWerd +
Joris Van den Bossche +
Juraj Niznan +
Karmel Allison
Kelsey Jordahl
Kevin Stone +
Kieran O’Mahony
Kyle Meyer +
Mike Kelly +
PKEuS +
Patrick O’Brien +
Phillip Cloud
Richard Höchenberger +
Skipper Seabold
SleepingPills +
Tobias Brandt
Tom Farnbauer +
TomAugspurger +
Trent Hauck +
Wes McKinney
Wouter Overmeire
Yaroslav Halchenko
conmai +
danielballan +
davidshinn +
dieterv77
duozhang +
ejnens +
gliptak +
jniznan +
jreback
lexual
nipunreddevil +
ogiaquino +
stonebig +
tim smith +
timmie
y-p