版本 0.21.0 (2017年10月27日)#

这是从 0.20.3 版本以来的一个主要发行版,包含多项 API 变更、弃用、新功能、改进和性能提升,以及大量的错误修复。我们建议所有用户升级到此版本。

主要亮点包括

  • Apache Parquet 集成,包括一个新的顶层 read_parquet() 函数和 DataFrame.to_parquet() 方法,详见 此处

  • 新的面向用户的 pandas.api.types.CategoricalDtype,用于独立于数据指定分类类型,详见 此处

  • 在全 NaN Series/DataFrame 上调用 sumprod 的行为现在一致,并且不再依赖于是否安装了 bottleneck;以及在空 Series 上调用 sumprod 现在返回 NaN 而不是 0,详见 此处

  • PyPy 的兼容性修复,详见 此处

  • dropreindexrename API 的补充,使其更加一致,详见 此处

  • 新增方法 DataFrame.infer_objects (详见 此处) 和 GroupBy.pipe (详见 此处)。

  • 使用包含一个或多个缺失标签的标签列表进行索引已被弃用,并将在未来版本中引发 KeyError,详见 此处

更新前请查阅 API 变更弃用

新功能#

与 Apache Parquet 文件格式集成#

Apache Parquet 集成,包括一个新的顶层 read_parquet()DataFrame.to_parquet() 方法,详见 此处 (GH 15838, GH 17438)。

Apache Parquet 提供了一种跨语言的二进制文件格式,用于高效地读写数据帧。Parquet 旨在忠实地序列化和反序列化 DataFrame,支持所有 pandas 数据类型,包括带时区的 datetime 等扩展数据类型。

此功能依赖于 pyarrowfastparquet 库。更多详情,请参阅 Parquet 的 IO 文档

方法 infer_objects 类型转换#

已新增 DataFrame.infer_objects()Series.infer_objects() 方法,用于对对象列执行 dtype 推断,取代了已弃用的 convert_objects 方法的部分功能。更多详情,请参阅此处的文档。 (GH 11221)

此方法仅对对象列执行软转换,将 Python 对象转换为原生类型,但不进行任何强制转换。例如

In [1]: df = pd.DataFrame({'A': [1, 2, 3],
   ...:                    'B': np.array([1, 2, 3], dtype='object'),
   ...:                    'C': ['1', '2', '3']})
   ...: 

In [2]: df.dtypes
Out[2]: 
A     int64
B    object
C    object
Length: 3, dtype: object

In [3]: df.infer_objects().dtypes
Out[3]: 
A     int64
B     int64
C    object
Length: 3, dtype: object

请注意,列 'C' 未转换——只有标量数值类型会被转换为新类型。其他类型的转换应使用 to_numeric() 函数(或 to_datetime()to_timedelta())完成。

In [4]: df = df.infer_objects()

In [5]: df['C'] = pd.to_numeric(df['C'], errors='coerce')

In [6]: df.dtypes
Out[6]: 
A    int64
B    int64
C    int64
Length: 3, dtype: object

尝试创建列时改进警告#

新用户常常对 DataFrame 实例上的列操作与属性访问之间的关系感到困惑 (GH 7175)。这种困惑的一个具体表现是尝试通过设置 DataFrame 上的属性来创建新列

In [1]: df = pd.DataFrame({'one': [1., 2., 3.]})
In [2]: df.two = [4, 5, 6]

这不会引发任何明显的异常,但也不会创建新列

In [3]: df
Out[3]:
    one
0  1.0
1  2.0
2  3.0

现在,将类列表数据结构设置为新属性会引发 UserWarning,提示可能出现意外行为。请参阅属性访问

方法 drop 现在也接受 index/columns 关键词#

drop() 方法新增了 index/columns 关键词,作为指定 axis 的替代方案。这与 reindex 的行为类似 (GH 12392)。

例如

In [7]: df = pd.DataFrame(np.arange(8).reshape(2, 4),
   ...:                   columns=['A', 'B', 'C', 'D'])
   ...: 

In [8]: df
Out[8]: 
   A  B  C  D
0  0  1  2  3
1  4  5  6  7

[2 rows x 4 columns]

In [9]: df.drop(['B', 'C'], axis=1)
Out[9]: 
   A  D
0  0  3
1  4  7

[2 rows x 2 columns]

# the following is now equivalent
In [10]: df.drop(columns=['B', 'C'])
Out[10]: 
   A  D
0  0  3
1  4  7

[2 rows x 2 columns]

方法 renamereindex 现在也接受 axis 关键词#

DataFrame.rename()DataFrame.reindex() 方法新增了 axis 关键词,用于指定操作的目标轴 (GH 12392)。

这是 rename

In [11]: df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]})

In [12]: df.rename(str.lower, axis='columns')
Out[12]: 
   a  b
0  1  4
1  2  5
2  3  6

[3 rows x 2 columns]

In [13]: df.rename(id, axis='index')
Out[13]: 
                 A  B
140277028225232  1  4
140277028225264  2  5
140277028225296  3  6

[3 rows x 2 columns]

以及 reindex

In [14]: df.reindex(['A', 'B', 'C'], axis='columns')
Out[14]: 
   A  B   C
0  1  4 NaN
1  2  5 NaN
2  3  6 NaN

[3 rows x 3 columns]

In [15]: df.reindex([0, 1, 3], axis='index')
Out[15]: 
     A    B
0  1.0  4.0
1  2.0  5.0
3  NaN  NaN

[3 rows x 2 columns]

“index, columns” 样式继续像以前一样工作。

In [16]: df.rename(index=id, columns=str.lower)
Out[16]: 
                 a  b
140277028225232  1  4
140277028225264  2  5
140277028225296  3  6

[3 rows x 2 columns]

In [17]: df.reindex(index=[0, 1, 3], columns=['A', 'B', 'C'])
Out[17]: 
     A    B   C
0  1.0  4.0 NaN
1  2.0  5.0 NaN
3  NaN  NaN NaN

[3 rows x 3 columns]

我们强烈建议使用命名参数,以避免在使用任一样式时产生混淆。

用于指定分类的 CategoricalDtype#

pandas.api.types.CategoricalDtype 已添加到公共 API 并扩展,以包含 categoriesordered 属性。一个 CategoricalDtype 可用于指定数组的类别集和有序性,独立于数据。这例如在将字符串数据转换为 Categorical 时非常有用 (GH 14711, GH 15078, GH 16015, GH 17643)

In [18]: from pandas.api.types import CategoricalDtype

In [19]: s = pd.Series(['a', 'b', 'c', 'a'])  # strings

In [20]: dtype = CategoricalDtype(categories=['a', 'b', 'c', 'd'], ordered=True)

In [21]: s.astype(dtype)
Out[21]: 
0    a
1    b
2    c
3    a
Length: 4, dtype: category
Categories (4, object): ['a' < 'b' < 'c' < 'd']

值得特别提及的一点是 read_csv()。以前,当使用 dtype={'col': 'category'} 时,返回的值和类别总是字符串。

In [22]: data = 'A,B\na,1\nb,2\nc,3'

In [23]: pd.read_csv(StringIO(data), dtype={'B': 'category'}).B.cat.categories
Out[23]: Index(['1', '2', '3'], dtype='object')

请注意“object” dtype。

对于包含所有数值、日期时间或时间增量的 CategoricalDtype,我们可以自动转换为正确的类型

In [24]: dtype = {'B': CategoricalDtype([1, 2, 3])}

In [25]: pd.read_csv(StringIO(data), dtype=dtype).B.cat.categories
Out[25]: Index([1, 2, 3], dtype='int64')

这些值已被正确解释为整数。

CategoricalCategoricalIndex 或分类类型 Series.dtype 属性现在将返回 CategoricalDtype 的实例。虽然表示(repr)已更改,但 str(CategoricalDtype()) 仍然是字符串 'category'。我们在此提醒用户,检测分类数据首选的方式是使用 pandas.api.types.is_categorical_dtype(),而不是 str(dtype) == 'category'

更多详情,请参阅CategoricalDtype 文档

GroupBy 对象现在拥有 pipe 方法#

GroupBy 对象现在拥有 pipe 方法,类似于 DataFrameSeries 上的方法,允许以清晰、可读的语法组合接受 GroupBy 的函数。 (GH 17871)

关于结合 .groupby.pipe 的具体示例,假设有一个 DataFrame,包含商店、产品、收入和销售数量的列。我们希望按商店和产品进行分组计算价格(即收入/数量)。我们可以通过多步操作完成此任务,但使用管道(piping)来表达可以使代码更具可读性。

首先我们设置数据

In [26]: import numpy as np

In [27]: n = 1000

In [28]: df = pd.DataFrame({'Store': np.random.choice(['Store_1', 'Store_2'], n),
   ....:                    'Product': np.random.choice(['Product_1',
   ....:                                                 'Product_2',
   ....:                                                 'Product_3'
   ....:                                                 ], n),
   ....:                    'Revenue': (np.random.random(n) * 50 + 10).round(2),
   ....:                    'Quantity': np.random.randint(1, 10, size=n)})
   ....: 

In [29]: df.head(2)
Out[29]: 
     Store    Product  Revenue  Quantity
0  Store_2  Product_2    32.09         7
1  Store_1  Product_3    14.20         1

[2 rows x 4 columns]

现在,要查找每个商店/产品的价格,我们只需执行

In [30]: (df.groupby(['Store', 'Product'])
   ....:    .pipe(lambda grp: grp.Revenue.sum() / grp.Quantity.sum())
   ....:    .unstack().round(2))
   ....: 
Out[30]: 
Product  Product_1  Product_2  Product_3
Store                                   
Store_1       6.73       6.72       7.14
Store_2       7.59       6.98       7.23

[2 rows x 3 columns]

更多详情,请参阅文档

Categorical.rename_categories 接受类字典参数#

rename_categories() 现在接受一个类字典参数作为 new_categories。之前的类别会在字典的键中查找,如果找到则替换。缺失和额外键的行为与 DataFrame.rename() 中相同。

In [31]: c = pd.Categorical(['a', 'a', 'b'])

In [32]: c.rename_categories({"a": "eh", "b": "bee"})
Out[32]: 
['eh', 'eh', 'bee']
Categories (2, object): ['eh', 'bee']

警告

为了帮助升级 pandas,rename_categoriesSeries 视为类列表。通常,Series 被认为是类字典(例如在 .rename.map 中)。在未来的 pandas 版本中,rename_categories 将改为将它们视为类字典。请遵循警告消息的建议,编写面向未来的代码。

In [33]: c.rename_categories(pd.Series([0, 1], index=['a', 'c']))
FutureWarning: Treating Series 'new_categories' as a list-like and using the values.
In a future version, 'rename_categories' will treat Series like a dictionary.
For dict-like, use 'new_categories.to_dict()'
For list-like, use 'new_categories.values'.
Out[33]:
[0, 0, 1]
Categories (2, int64): [0, 1]

其他改进#

新函数或方法#

新关键词#

各项改进#

向后不兼容的 API 变更#

依赖项的最低版本已提高#

我们已更新了依赖项的最低支持版本 (GH 15206, GH 15543, GH 15214)。如果已安装,我们现在要求

最低版本

必需

Numpy

1.9.0

X

Matplotlib

1.4.3

Scipy

0.14.0

Bottleneck

1.0.0

此外,已停止对 Python 3.4 的支持 (GH 15251)。

全 NaN 或空 Series/DataFrame 的求和/乘积现在一致地为 NaN#

注意

此处描述的更改已部分恢复。更多详情,请参阅v0.22.0 新特性

sumprod 在全 NaN Series/DataFrame 上的行为不再依赖于是否安装了 bottleneck,并且在空 Series 上调用 sumprod 的返回值已更改 (GH 9422, GH 15507)。

在空或全 NaNSeriesDataFrame 列上调用 sumprod 将导致 NaN。详见文档

In [33]: s = pd.Series([np.nan])

以前,在未安装 bottleneck 的情况下

In [2]: s.sum()
Out[2]: np.nan

以前,在安装了 bottleneck 的情况下

In [2]: s.sum()
Out[2]: 0.0

新行为,不考虑 bottleneck 的安装情况

In [34]: s.sum()
Out[34]: 0.0

请注意,这也会改变空 Series 的求和结果。以前,无论是否安装 bottleneck,这总是返回 0

In [1]: pd.Series([]).sum()
Out[1]: 0

但为了与全 NaN 情况保持一致,这也已更改为返回 NaN。

In [2]: pd.Series([]).sum()
Out[2]: 0

使用包含缺失标签的列表进行索引已被弃用#

以前,使用包含一个或多个缺失标签的标签列表进行选择总是会成功,并为缺失的标签返回 NaN。现在,这会显示一个 FutureWarning。未来这将引发 KeyError (GH 15747)。当使用包含至少 1 个缺失标签的标签列表时,此警告将在对 DataFrameSeries 使用 .loc[][[]] 时触发。

In [35]: s = pd.Series([1, 2, 3])

In [36]: s
Out[36]: 
0    1
1    2
2    3
Length: 3, dtype: int64

旧行为

In [4]: s.loc[[1, 2, 3]]
Out[4]:
1    2.0
2    3.0
3    NaN
dtype: float64

当前行为

In [4]: s.loc[[1, 2, 3]]
Passing list-likes to .loc or [] with any missing label will raise
KeyError in the future, you can use .reindex() as an alternative.

See the documentation here:
https://pandas.ac.cn/pandas-docs/stable/indexing.html#deprecate-loc-reindex-listlike

Out[4]:
1    2.0
2    3.0
3    NaN
dtype: float64

选择可能不存在的元素的惯用方法是通过 .reindex()

In [37]: s.reindex([1, 2, 3])
Out[37]: 
1    2.0
2    3.0
3    NaN
Length: 3, dtype: float64

所有键都存在的选择行为不变。

In [38]: s.loc[[1, 2]]
Out[38]: 
1    2
2    3
Length: 2, dtype: int64

NA 命名变更#

为了提高 pandas API 的一致性,我们添加了额外的顶级函数 isna()notna(),它们是 isnull()notnull() 的别名。命名方案现在与 .dropna().fillna() 等方法更加一致。此外,在所有定义了 .isnull().notnull() 方法的情况下,这些方法都新增了名为 .isna().notna() 的方法,它们已包含在 CategoricalIndexSeriesDataFrame 类中。 (GH 15001)。

配置选项 pd.options.mode.use_inf_as_null 已被弃用,并新增 pd.options.mode.use_inf_as_na 作为替代。

Series/Index 的迭代现在将返回 Python 标量#

以前,当对 dtype 为 intfloatSeries 使用某些迭代方法时,您会收到一个 numpy 标量(例如 np.int64),而不是 Python int。问题 (GH 10904) 修复了 Series.tolist()list(Series) 的此问题。此更改使得所有迭代方法保持一致,特别是对于 __iter__().map();请注意,这仅影响 int/float 数据类型。 (GH 13236, GH 13258, GH 14216)。

In [39]: s = pd.Series([1, 2, 3])

In [40]: s
Out[40]: 
0    1
1    2
2    3
Length: 3, dtype: int64

以前

In [2]: type(list(s)[0])
Out[2]: numpy.int64

新行为

In [41]: type(list(s)[0])
Out[41]: int

此外,这现在还会正确地将 DataFrame.to_dict() 的迭代结果进行装箱。

In [42]: d = {'a': [1], 'b': ['b']}

In [43]: df = pd.DataFrame(d)

以前

In [8]: type(df.to_dict()['a'][0])
Out[8]: numpy.int64

新行为

In [44]: type(df.to_dict()['a'][0])
Out[44]: int

使用布尔索引进行索引#

以前,当将布尔型 Index 传递给 .loc 时,如果 Series/DataFrame 的索引具有 boolean 标签,您将获得基于标签的选择,可能会重复结果标签,而不是布尔索引选择(其中 True 选择元素),这与布尔型 numpy 数组索引的方式不一致。新行为是像布尔型 numpy 数组索引器那样操作。 (GH 17738)

旧行为

In [45]: s = pd.Series([1, 2, 3], index=[False, True, False])

In [46]: s
Out[46]: 
False    1
True     2
False    3
Length: 3, dtype: int64
In [59]: s.loc[pd.Index([True, False, True])]
Out[59]:
True     2
False    1
False    3
True     2
dtype: int64

当前行为

In [47]: s.loc[pd.Index([True, False, True])]
Out[47]: 
False    1
False    3
Length: 2, dtype: int64

此外,以前如果您有一个非数值型索引(例如字符串),那么布尔型 Index 将引发 KeyError。现在,这将视为一个布尔索引器。

旧行为

In [48]: s = pd.Series([1, 2, 3], index=['a', 'b', 'c'])

In [49]: s
Out[49]: 
a    1
b    2
c    3
Length: 3, dtype: int64
In [39]: s.loc[pd.Index([True, False, True])]
KeyError: "None of [Index([True, False, True], dtype='object')] are in the [index]"

当前行为

In [50]: s.loc[pd.Index([True, False, True])]
Out[50]: 
a    1
c    3
Length: 2, dtype: int64

PeriodIndex 重采样#

在以前的 pandas 版本中,对由 PeriodIndex 索引的 Series/DataFrame 进行重采样在某些情况下会返回 DatetimeIndex (GH 12884)。现在,重采样到倍数频率会返回一个 PeriodIndex (GH 15944)。作为一个小改进,PeriodIndex 的重采样现在可以处理 NaT 值 (GH 13224)

旧行为

In [1]: pi = pd.period_range('2017-01', periods=12, freq='M')

In [2]: s = pd.Series(np.arange(12), index=pi)

In [3]: resampled = s.resample('2Q').mean()

In [4]: resampled
Out[4]:
2017-03-31     1.0
2017-09-30     5.5
2018-03-31    10.0
Freq: 2Q-DEC, dtype: float64

In [5]: resampled.index
Out[5]: DatetimeIndex(['2017-03-31', '2017-09-30', '2018-03-31'], dtype='datetime64[ns]', freq='2Q-DEC')

新行为

In [1]: pi = pd.period_range('2017-01', periods=12, freq='M')

In [2]: s = pd.Series(np.arange(12), index=pi)

In [3]: resampled = s.resample('2Q').mean()

In [4]: resampled
Out[4]:
2017Q1    2.5
2017Q3    8.5
Freq: 2Q-DEC, dtype: float64

In [5]: resampled.index
Out[5]: PeriodIndex(['2017Q1', '2017Q3'], dtype='period[2Q-DEC]')

上采样并调用 .ohlc() 以前返回一个 Series,基本上与调用 .asfreq() 相同。OHLC 上采样现在返回一个包含 openhighlowclose 列的 DataFrame (GH 13083)。这与下采样和 DatetimeIndex 的行为一致。

旧行为

In [1]: pi = pd.period_range(start='2000-01-01', freq='D', periods=10)

In [2]: s = pd.Series(np.arange(10), index=pi)

In [3]: s.resample('H').ohlc()
Out[3]:
2000-01-01 00:00    0.0
                ...
2000-01-10 23:00    NaN
Freq: H, Length: 240, dtype: float64

In [4]: s.resample('M').ohlc()
Out[4]:
         open  high  low  close
2000-01     0     9    0      9

新行为

In [56]: pi = pd.period_range(start='2000-01-01', freq='D', periods=10)

In [57]: s = pd.Series(np.arange(10), index=pi)

In [58]: s.resample('H').ohlc()
Out[58]:
                  open  high  low  close
2000-01-01 00:00   0.0   0.0  0.0    0.0
2000-01-01 01:00   NaN   NaN  NaN    NaN
2000-01-01 02:00   NaN   NaN  NaN    NaN
2000-01-01 03:00   NaN   NaN  NaN    NaN
2000-01-01 04:00   NaN   NaN  NaN    NaN
...                ...   ...  ...    ...
2000-01-10 19:00   NaN   NaN  NaN    NaN
2000-01-10 20:00   NaN   NaN  NaN    NaN
2000-01-10 21:00   NaN   NaN  NaN    NaN
2000-01-10 22:00   NaN   NaN  NaN    NaN
2000-01-10 23:00   NaN   NaN  NaN    NaN

[240 rows x 4 columns]

In [59]: s.resample('M').ohlc()
Out[59]:
         open  high  low  close
2000-01     0     9    0      9

[1 rows x 4 columns]

pd.eval 中项赋值的错误处理改进#

eval() 现在会在项赋值出错或指定原地操作但表达式中没有项赋值时引发 ValueError (GH 16732)

In [51]: arr = np.array([1, 2, 3])

以前,如果您尝试以下表达式,您会得到一个不太有用的错误消息

In [3]: pd.eval("a = 1 + 2", target=arr, inplace=True)
...
IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`)
and integer or boolean arrays are valid indices

这是一种非常冗长的方式来说明 numpy 数组不支持字符串项索引。通过此更改,错误消息现在是这样

In [3]: pd.eval("a = 1 + 2", target=arr, inplace=True)
...
ValueError: Cannot assign expression output to target

以前,即使没有项赋值,也可以原地(inplace)评估表达式。

In [4]: pd.eval("1 + 2", target=arr, inplace=True)
Out[4]: 3

然而,这种输入意义不大,因为输出未被赋值给目标。现在,当传入此类输入时,将引发 ValueError

In [4]: pd.eval("1 + 2", target=arr, inplace=True)
...
ValueError: Cannot operate inplace if there is no assignment

数据类型转换#

以前,带有 bool 赋值的赋值操作、.where().fillna() 会强制转换为相同的类型(例如 int / float),或者对日期时间类型引发错误。现在,这些操作将保留布尔值,并将其 dtype 设置为 object。 (GH 16821)。

In [52]: s = pd.Series([1, 2, 3])
In [5]: s[1] = True

In [6]: s
Out[6]:
0    1
1    1
2    3
dtype: int64

新行为

In [7]: s[1] = True

In [8]: s
Out[8]:
0       1
1    True
2       3
Length: 3, dtype: object

以前,将非日期时间类型赋值给日期时间类型时,会被强制转换 (GH 14145)。

In [53]: s = pd.Series([pd.Timestamp('2011-01-01'), pd.Timestamp('2012-01-01')])
In [1]: s[1] = 1

In [2]: s
Out[2]:
0   2011-01-01 00:00:00.000000000
1   1970-01-01 00:00:00.000000001
dtype: datetime64[ns]

这些现在会被强制转换为 object dtype。

In [1]: s[1] = 1

In [2]: s
Out[2]:
0    2011-01-01 00:00:00
1                      1
dtype: object
  • .where() 在处理日期时间类型时存在不一致行为,会引发错误而不是强制转换为 object (GH 16402)

  • float64 dtype 的 np.ndarray 赋值给 int64 数据时可能保留 int64 dtype 的错误 (GH 14001)

单层 MultiIndex 构造函数#

MultiIndex 构造函数不再将所有长度为一的 MultiIndex 压缩为常规 Index。这会影响所有的 MultiIndex 构造函数。 (GH 17178)

旧行为

In [2]: pd.MultiIndex.from_tuples([('a',), ('b',)])
Out[2]: Index(['a', 'b'], dtype='object')

长度为 1 的层不再作为特殊情况处理。它们的行为与长度为 2+ 的层完全相同,因此所有 MultiIndex 构造函数都将始终返回 MultiIndex

In [54]: pd.MultiIndex.from_tuples([('a',), ('b',)])
Out[54]: 
MultiIndex([('a',),
            ('b',)],
           )

Series 的 UTC 本地化#

以前,当传递 utc=True 时,to_datetime() 不会对日期时间 Series 数据进行本地化。现在,to_datetime() 将正确地将具有 datetime64[ns, UTC] dtype 的 Series 本地化,以与类列表和 Index 数据的处理方式保持一致。 (GH 6415)。

旧行为

In [55]: s = pd.Series(['20130101 00:00:00'] * 3)
In [12]: pd.to_datetime(s, utc=True)
Out[12]:
0   2013-01-01
1   2013-01-01
2   2013-01-01
dtype: datetime64[ns]

新行为

In [56]: pd.to_datetime(s, utc=True)
Out[56]: 
0   2013-01-01 00:00:00+00:00
1   2013-01-01 00:00:00+00:00
2   2013-01-01 00:00:00+00:00
Length: 3, dtype: datetime64[ns, UTC]

此外,由 read_sql_table()read_sql_query() 解析的带有日期时间列的 DataFrame 也将仅在原始 SQL 列是时区感知日期时间列时才本地化为 UTC。

范围函数的一致性#

在以前的版本中,各种范围函数之间存在一些不一致性:date_range()bdate_range()period_range()timedelta_range()interval_range()。 (GH 17471)。

当同时指定 startendperiod 参数时,可能导致范围模糊,这是不一致行为之一。当传递所有三个参数时,interval_range 会忽略 period 参数,period_range 会忽略 end 参数,而其他范围函数则会引发错误。为了提高范围函数之间的一致性并避免潜在的模糊范围,当传递所有三个参数时,interval_rangeperiod_range 现在将引发错误。

旧行为

 In [2]: pd.interval_range(start=0, end=4, periods=6)
 Out[2]:
 IntervalIndex([(0, 1], (1, 2], (2, 3]]
               closed='right',
               dtype='interval[int64]')

In [3]: pd.period_range(start='2017Q1', end='2017Q4', periods=6, freq='Q')
Out[3]: PeriodIndex(['2017Q1', '2017Q2', '2017Q3', '2017Q4', '2018Q1', '2018Q2'], dtype='period[Q-DEC]', freq='Q-DEC')

新行为

In [2]: pd.interval_range(start=0, end=4, periods=6)
---------------------------------------------------------------------------
ValueError: Of the three parameters: start, end, and periods, exactly two must be specified

In [3]: pd.period_range(start='2017Q1', end='2017Q4', periods=6, freq='Q')
---------------------------------------------------------------------------
ValueError: Of the three parameters: start, end, and periods, exactly two must be specified

此外,interval_range 生成的区间不包含端点参数 end。然而,所有其他范围函数都在其输出中包含 end。为了促进范围函数之间的一致性,interval_range 现在将把 end 作为最终区间的右端点包含在内,除非 freq 的指定方式跳过了 end

旧行为

In [4]: pd.interval_range(start=0, end=4)
Out[4]:
IntervalIndex([(0, 1], (1, 2], (2, 3]]
              closed='right',
              dtype='interval[int64]')

新行为

In [57]: pd.interval_range(start=0, end=4)
Out[57]: IntervalIndex([(0, 1], (1, 2], (2, 3], (3, 4]], dtype='interval[int64, right]')

不再自动注册 Matplotlib 转换器#

pandas 在导入时不再自动注册我们针对 matplotlib 的 datetimedatetimedatetime64Period 转换器。Matplotlib 绘图方法(plt.plot, ax.plot, …)将不会为 DatetimeIndexPeriodIndex 值提供漂亮的 X 轴格式。您必须显式注册这些方法

pandas 内置的 Series.plotDataFrame.plot 在首次使用时注册这些转换器 (GH 17710)。

注意

此更改已在 pandas 0.21.1 中暂时恢复,更多详情请参阅此处

其他 API 变更#

  • Categorical 构造函数不再接受标量作为 categories 关键词。 (GH 16022)

  • 在已关闭的 HDFStore 上访问不存在的属性现在将引发 AttributeError,而不是 ClosedFileError (GH 16301)

  • read_csv() 现在会在 names 参数包含重复项时发出 UserWarning (GH 17095)

  • read_csv() 现在默认将字符串 'null''n/a' 视为空值 (GH 16471, GH 16078)

  • pandas.HDFStore 的字符串表示现在更快,且细节更少。如需之前的行为,请使用 pandas.HDFStore.info()。(GH 16503)。

  • HDF 存储中的压缩默认值现在遵循 pytables 标准。默认不压缩,如果缺少 complibcomplevel > 0,则使用 zlib (GH 15943)

  • Index.get_indexer_non_unique() 现在返回一个 ndarray 索引器而不是 Index;这与 Index.get_indexer() 保持一致 (GH 16819)

  • pandas._testing 中移除了 @slow 装饰器,该装饰器导致一些下游包的测试套件出现问题。请改用 @pytest.mark.slow,它能实现相同的功能 (GH 16850)

  • MergeError 的定义移至 pandas.errors 模块。

  • Series.set_axis()DataFrame.set_axis() 的签名已从 set_axis(axis, labels) 更改为 set_axis(labels, axis=0),以与 API 的其余部分保持一致。旧签名已被弃用,并将显示 FutureWarning (GH 14636)

  • Series.argmin()Series.argmax() 在与 object dtypes 一起使用时,现在将引发 TypeError,而不是 ValueError (GH 13595)

  • Period 现在是不可变的,当用户尝试为 ordinalfreq 属性赋值时,将引发 AttributeError (GH 17116)。

  • to_datetime() 传入时区感知的 origin= 关键字参数时,现在将引发更具信息量的 ValueError,而不是 TypeError (GH 16842)

  • to_datetime() 现在在格式包含 %W%U 但没有同时包含星期几和日历年份时,会引发 ValueError (GH 16774)

  • 为提高 API 一致性,已将 read_stata() 中非功能的 index 重命名为 index_col (GH 16342)

  • DataFrame.drop() 中的一个错误导致在从数字索引中删除索引时,布尔标签 FalseTrue 分别被视为标签 0 和 1。现在这将引发 ValueError (GH 16877)

  • 限制了 DateOffset 关键字参数。以前,DateOffset 子类允许任意关键字参数,这可能导致意外行为。现在,只接受有效参数。( GH 17176)。

弃用#

  • DataFrame.from_csv()Series.from_csv() 已被弃用,取而代之的是 read_csv() (GH 4191)

  • read_excel() 已弃用 sheetname,取而代之的是 sheet_name,以与 .to_excel() 保持一致 (GH 10559)。

  • read_excel() 已弃用 parse_cols,取而代之的是 usecols,以与 read_csv() 保持一致 (GH 4988)

  • read_csv() 已弃用 tupleize_cols 参数。列元组将始终转换为 MultiIndex (GH 17060)

  • DataFrame.to_csv() 已弃用 tupleize_cols 参数。MultiIndex 列将始终以行形式写入 CSV 文件 (GH 17060)

  • .take() 方法中,convert 参数已被弃用,因为它未被遵守 (GH 16948)

  • pd.options.html.border 已弃用,取而代之的是 pd.options.display.html.border (GH 15793)。

  • SeriesGroupBy.nth() 已弃用 True,取而代之的是 'all' 作为其 kwarg dropna 的值 (GH 11038)。

  • DataFrame.as_blocks() 已弃用,因为它暴露了内部实现 (GH 17302)

  • pd.TimeGrouper 已弃用,取而代之的是 pandas.Grouper (GH 16747)

  • cdate_range 已弃用,取而代之的是 bdate_range(),后者增加了 weekmaskholidays 参数,用于构建自定义频率日期范围。详情请参阅文档 (GH 17596)

  • 已弃用向 Series.astype() 传递 categoriesordered 关键字参数,取而代之的是传递 CategoricalDtype (GH 17636)

  • SeriesDataFramePanelSparseSeriesSparseDataFrame 上的 .get_value.set_value 已弃用,取而代之的是使用 .iat[].at[] 访问器 (GH 15269)

  • .to_excel(..., columns=) 中传入不存在的列已被弃用,将来会引发 KeyError (GH 17295)

  • Series.where()Series.mask()DataFrame.where()DataFrame.mask() 中的 raise_on_error 参数已弃用,取而代之的是 errors= (GH 14968)

  • 使用 DataFrame.rename_axis()Series.rename_axis() 更改索引或列的标签现在已被弃用,取而代之的是使用 .renamerename_axis 仍可用于更改索引或列的名称 (GH 17833)。

  • reindex_axis() 已弃用,取而代之的是 reindex()。更多详情请参阅 此处 (GH 17833)。

Series.select 和 DataFrame.select#

Series.select()DataFrame.select() 方法已弃用,取而代之的是使用 df.loc[labels.map(crit)] (GH 12401)

In [58]: df = pd.DataFrame({'A': [1, 2, 3]}, index=['foo', 'bar', 'baz'])
In [3]: df.select(lambda x: x in ['bar', 'baz'])
FutureWarning: select is deprecated and will be removed in a future release. You can use .loc[crit] as a replacement
Out[3]:
     A
bar  2
baz  3
In [59]: df.loc[df.index.map(lambda x: x in ['bar', 'baz'])]
Out[59]: 
     A
bar  2
baz  3

[2 rows x 1 columns]

Series.argmax 和 Series.argmin#

Series.argmax()Series.argmin() 的行为已被弃用,取而代之的是 Series.idxmax()Series.idxmin() (GH 16830)。

为了与 NumPy 数组兼容,pd.Series 实现了 argmaxargmin。自 pandas 0.13.0 以来,argmax 一直是 pandas.Series.idxmax() 的别名,argmin 一直是 pandas.Series.idxmin() 的别名。它们返回最大值或最小值的标签,而不是位置

我们已弃用 Series.argmaxSeries.argmin 的当前行为。使用它们中的任何一个都将发出 FutureWarning。如果您想要最大值的标签,请使用 Series.idxmax()。如果您想要最大值的位置,请使用 Series.values.argmax()。最小值同理。在未来的版本中,Series.argmaxSeries.argmin 将返回最大值或最小值的位置。

移除以前版本中弃用的功能/更改#

  • read_excel() 已删除 has_index_names 参数 (GH 10967)

  • pd.options.display.height 配置已被删除 (GH 3663)

  • pd.options.display.line_width 配置已被删除 (GH 2881)

  • pd.options.display.mpl_style 配置已被删除 (GH 12190)

  • Index 已删除 .sym_diff() 方法,取而代之的是 .symmetric_difference() (GH 12591)

  • Categorical 已删除 .order().sort() 方法,取而代之的是 .sort_values() (GH 12882)

  • eval()DataFrame.eval() 已将 inplace 的默认值从 None 更改为 False (GH 11149)

  • 函数 get_offset_name 已被删除,取而代之的是偏移量的 .freqstr 属性 (GH 11834)

  • pandas 不再测试与 pandas < 0.11 创建的 hdf5 文件的兼容性 (GH 17404)。

性能改进#

文档更改#

Bug 修复#

转换#

  • 在对 datetime-like 数据使用 int 进行赋值时,可能错误地转换为 datetime-like 类型 (GH 14145)

  • float64 dtype 的 np.ndarray 赋值给 int64 数据时可能保留 int64 dtype 的错误 (GH 14001)

  • 修复了 IntervalIndex.is_non_overlapping_monotonic 的返回类型,使其成为 Python 的 bool,以与类似属性/方法保持一致。以前返回 numpy.bool_。(GH 17237)

  • IntervalIndex.is_non_overlapping_monotonic 中的一个错误,当区间两端都封闭并在一个点重叠时 (GH 16560)

  • Series.fillna() 中的一个错误,当 inplace=Truevalue 是字典时,会返回 DataFrame (GH 16156)

  • Timestamp.weekday_name 中的一个错误,在本地化到时区时返回基于 UTC 的星期几名称 (GH 17354)

  • Timestamp.replace 中替换 tzinfo 遇到夏令时变更时的错误 (GH 15683)

  • Timedelta 构造和算术中的一个错误,该错误不会传播 Overflow 异常 (GH 17367)

  • astype() 中的一个错误,当传递扩展类型类(DatetimeTZDtypeCategoricalDtype)而不是实例时,会转换为 object dtype。现在,当传递类时会引发 TypeError (GH 17780)。

  • to_numeric() 中的一个错误,其中当 errors='coerce' 时,元素并不总是强制转换为数字类型 (GH 17007, GH 17125)

  • DataFrameSeries 构造函数中的一个错误,其中 range 对象在 Windows 上被转换为 int32 dtype 而不是 int64 (GH 16804)

索引#

  • 当使用空切片(例如 df.iloc[:])调用时,.iloc.loc 索引器返回原始对象的浅拷贝。以前它们返回原始对象。(GH 13873)。

  • 当在未排序的 MultiIndex 上调用时,loc 索引器现在仅在非排序级别上使用适当的切片时才会引发 UnsortedIndexError (GH 16734)。

  • 修复了 0.20.3 中使用字符串对 TimedeltaIndex 进行索引时的回归 (GH 16896)。

  • 修复了 TimedeltaIndex.get_loc()np.timedelta64 输入的处理 (GH 16909)。

  • 修复 MultiIndex.sort_index()ascending 参数是一个列表但并非所有级别都已指定或以不同顺序排列时的排序问题 (GH 16934)。

  • 修复了使用 np.inf 进行索引时导致引发 OverflowError 的错误 (GH 16957)

  • 在空 CategoricalIndex 上重新索引时的错误 (GH 16770)

  • 修复了 DataFrame.loc 用于带对齐和时区感知 DatetimeIndex 的设置 (GH 16889)

  • 避免在使用较旧的 numpy 时,将 Index 或 Series 传递给 .iloc 导致 IndexError (GH 17193)

  • 允许在 Python 2 中将 Unicode 空字符串作为多级列中的占位符 (GH 17099)

  • .iloc 在与就地加法或赋值以及 MultiIndex 上的 int 索引器一起使用时,导致读取和写入错误的索引的错误 (GH 17148)

  • .isin() 中的一个错误,其中检查空 Series 对象的成员资格时会引发错误 (GH 16991)

  • CategoricalIndex 重新索引中的一个错误,其中包含重复项的指定索引未被遵守 (GH 17323)

  • RangeIndex 与负步长的交集错误 (GH 17296)

  • IntervalIndex 中的一个错误,其中对非重叠单调递减索引的包含右端点进行标量查找失败 (GH 16417, GH 17271)

  • DataFrame.first_valid_index()DataFrame.last_valid_index() 在没有有效条目时的错误 (GH 17400)

  • Series.rename() 在使用可调用对象调用时,错误地更改了 Series 的名称,而不是 Index 的名称。(GH 17407)

  • String.str_get() 在使用负索引时引发 IndexError 而不是插入 NaNs 的错误。( GH 17704)

I/O#

  • read_hdf() 读取 fixed 格式 HDFStore 中的时区感知索引时出现错误 (GH 17618)

  • read_csv() 中的一个错误,其中列没有被彻底去重 (GH 17060)

  • read_csv() 中的一个错误,其中指定的列名没有被彻底去重 (GH 17095)

  • read_csv() 中的一个错误,其中 header 参数的非整数值生成了无用/不相关的错误消息 (GH 16338)

  • read_csv() 中的一个错误,在某些条件下,异常处理中的内存管理问题会导致解释器段错误 (GH 14696, GH 16798)。

  • read_csv() 在调用时 low_memory=False 的一个错误,其中包含至少一个大于 2GB 的列的 CSV 文件会错误地引发 MemoryError (GH 16798)。

  • read_csv() 中的一个错误,当使用单元素列表 header 调用时,会返回一个包含所有 NaN 值的 DataFrame (GH 7757)

  • DataFrame.to_csv() 在 Python 3 中默认编码为“ascii”而不是“utf-8”的错误 (GH 17097)

  • read_stata() 中的一个错误,其中在使用迭代器时无法读取值标签 (GH 16923)

  • read_stata() 中的一个错误,其中索引未设置 (GH 16342)

  • read_html() 中的一个错误,其中在多线程运行时导入检查失败 (GH 16928)

  • read_csv() 中的一个错误,其中自动分隔符检测在遇到错误行时会抛出 TypeError 而不是正确的错误消息 (GH 13374)

  • DataFrame.to_html()notebook=True 时的一个错误,其中带有命名索引或非 MultiIndex 索引的 DataFrame 分别具有列标签或行标签的不需要的水平或垂直对齐 (GH 16792)

  • DataFrame.to_html() 中的一个错误,其中没有对 justify 参数进行验证 (GH 17527)

  • HDFStore.select() 在读取包含 VLArray 的连续混合数据表时的错误 (GH 17021)

  • to_json() 中的一个错误,其中几种情况(包括带有不可打印符号的对象、深度递归的对象、过长的标签)导致段错误而不是引发适当的异常 (GH 14256)

绘图#

  • 绘图方法中使用 secondary_yfontsize 时,未设置次轴字体大小的错误 (GH 12565)

  • 在 y 轴上绘制 timedeltadatetime dtypes 时的错误 (GH 16953)

  • 折线图在计算 x 轴限制时不再假设 x 数据是单调的,即使对于未排序的 x 数据,它们现在也显示完整的线条。(GH 11310, GH 11471)

  • 对于 matplotlib 2.0.0 及更高版本,折线图的 x 轴限制计算交由 matplotlib 处理,以便应用其新的默认设置。(GH 15495)

  • Series.plot.barDataFrame.plot.bary 不遵守用户传入的 color 时的错误 (GH 16822)

  • 导致 plotting.parallel_coordinates 在使用随机颜色时重置随机种子的错误 (GH 17525)

GroupBy/resample/rolling#

  • DataFrame.resample(...).size() 中的一个错误,其中空的 DataFrame 没有返回 Series (GH 14962)

  • infer_freq() 中的一个错误,导致工作周期间有 2 天间隔的索引被错误地推断为商务日频率 (GH 16624)

  • .rolling(...).quantile() 中的一个错误,它错误地使用了与 Series.quantile()DataFrame.quantile() 不同的默认值 (GH 9413, GH 16211)

  • groupby.transform() 中的一个错误,它会将布尔 dtype 强制转换回浮点数 (GH 16875)

  • Series.resample(...).apply() 中的一个错误,其中空的 Series 修改了源索引,并且没有返回 Series 的名称 (GH 14313)

  • .rolling(...).apply(...) 与带有 DatetimeIndexDataFrame、可转换为 timedelta 的 window 以及 min_periods >= 1 一起使用时的错误 (GH 15305)

  • DataFrame.groupby 中的一个错误,当键的数量等于 groupby 轴上的元素数量时,索引和列键未被正确识别 (GH 16859)

  • groupby.nunique()TimeGrouper 一起使用时无法正确处理 NaT 的错误 (GH 17575)

  • DataFrame.groupby 中的一个错误,其中从 MultiIndex 中选择单个级别会意外地排序 (GH 17537)

  • DataFrame.groupby 中的一个错误,其中当使用 Grouper 对象覆盖歧义列名时,会引发虚假警告 (GH 17383)

  • TimeGrouper 在作为列表和标量传递时表现不同 (GH 17530)

稀疏#

  • SparseSeries 在将字典作为数据传入时引发 AttributeError 的错误 (GH 16905)

  • SparseDataFrame.fillna() 未填充从 SciPy 稀疏矩阵实例化时的所有 NaNs 的错误 (GH 16112)

  • SparseSeries.unstack()SparseDataFrame.stack() 中的错误 (GH 16614, GH 15045)

  • make_sparse() 中的一个错误,当数组 dtypeobject 时,将具有相同位数的两个数字/布尔数据视为相同 (GH 17574)

  • SparseArray.all()SparseArray.any() 现在已实现以处理 SparseArray,这些已被使用但未实现 (GH 17570)

重塑#

  • 使用非唯一 PeriodIndex 进行连接/合并时引发 TypeError (GH 16871)

  • crosstab() 中的一个错误,其中非对齐的整数 Series 被转换为浮点数 (GH 17005)

  • 与具有布尔/整数数据类型的分类 dtype 进行合并时,错误地引发 TypeError 的错误 (GH 16900)

  • 在大型对象 Series 和大型比较数组上使用 isin() 时的错误 (GH 16012)

  • 修复了 0.20 版本的回归,Series.aggregate()DataFrame.aggregate() 再次允许字典作为返回值 (GH 16741)

  • 修复了当 pivot_table() 在调用时 margins=True 时,整数 dtype 输入的结果 dtype (GH 17013)

  • crosstab() 中的一个错误,其中传递两个同名的 Series 会引发 KeyError (GH 13279)

  • Series.argmin()Series.argmax() 以及它们在 DataFrame 和 groupby 对象上的对应方法,可以正确处理包含无穷大值的浮点数据 (GH 13595)。

  • unique() 中的一个错误,其中检查字符串元组时会引发 TypeError (GH 17108)

  • concat() 中的一个错误,当结果索引包含不可比较的元素时,其顺序不可预测 (GH 17344)

  • 修复了在具有 NaT 值的 datetime64 dtype Series 上按多列排序时的回归 (GH 16836)

  • pivot_table() 中的一个错误,当 dropnaFalse 时,结果的列未保留 columns 的分类 dtype (GH 17842)

  • DataFrame.drop_duplicates 中的一个错误,其中删除非唯一列名时引发 ValueError (GH 17836)

  • unstack() 中的一个错误,当在级别列表上调用时,会丢弃 fillna 参数 (GH 13971)

  • range 对象和其他列表状对象与 DataFrame 对齐时的一个错误,导致操作按行而不是按列执行 (GH 17901)

数值#

  • .clip()axis=1 且传入 threshold 为列表状对象时的一个错误;以前这会引发 ValueError (GH 15390)

  • Series.clip()DataFrame.clip() 现在将上限和下限参数的 NA 值视为 None,而不是引发 ValueError (GH 17276)。

分类#

  • Series.isin() 在使用分类数据调用时的错误 (GH 16639)

  • 使用空值和类别构建分类器时的一个错误,导致 .categories 成为空的 Float64Index 而不是带有 object dtype 的空 Index (GH 17248)

  • 分类操作中的一个错误,其中 Series.cat 未保留原始 Series 的名称 (GH 17509)

  • DataFrame.merge() 合并布尔/整数数据类型的分类列时失败的错误 (GH 17187)

  • 在指定 categories 为分类类型时,构造 Categorical/CategoricalDtype 的错误 (GH 17884)。

PyPy#

  • 与 PyPy 在 read_csv()usecols=[<unsorted ints>]read_json() 时的兼容性 (GH 17351)

  • 根据需要将测试拆分为 CPython 和 PyPy 的用例,这突出了索引匹配 float('nan')np.nanNAT 时的脆弱性 (GH 17351)

  • 修复了 DataFrame.memory_usage() 以支持 PyPy。PyPy 上的对象没有固定大小,因此改用近似值 (GH 17228)

其他#

  • 某些就地运算符未被包装并在调用时生成副本的错误 (GH 12962)

  • eval() 中的一个错误,其中 inplace 参数被错误地处理 (GH 16732)

贡献者#

共有 206 人为本次发布贡献了补丁。名字旁边带有“+”的人是首次贡献补丁。

  • 3553x +

  • Aaron Barber

  • Adam Gleave +

  • Adam Smith +

  • AdamShamlian +

  • Adrian Liaw +

  • Alan Velasco +

  • Alan Yee +

  • Alex B +

  • Alex Lubbock +

  • Alex Marchenko +

  • Alex Rychyk +

  • Amol K +

  • Andreas Winkler

  • Andrew +

  • Andrew 亮

  • André Jonasson +

  • Becky Sweger

  • Berkay +

  • Bob Haffner +

  • Bran Yang

  • Brian Tu +

  • Brock Mendel +

  • Carol Willing +

  • Carter Green +

  • Chankey Pathak +

  • Chris

  • Chris Billington

  • Chris Filo Gorgolewski +

  • Chris Kerr

  • Chris M +

  • Chris Mazzullo +

  • Christian Prinoth

  • Christian Stade-Schuldt

  • Christoph Moehl +

  • DSM

  • Daniel Chen +

  • Daniel Grady

  • Daniel Himmelstein

  • Dave Willmer

  • David Cook

  • David Gwynne

  • David Read +

  • Dillon Niederhut +

  • Douglas Rudd

  • Eric Stein +

  • Eric Wieser +

  • Erik Fredriksen

  • Florian Wilhelm +

  • Floris Kint +

  • Forbidden Donut

  • Gabe F +

  • Giftlin +

  • Giftlin Rajaiah +

  • Giulio Pepe +

  • Guilherme Beltramini

  • Guillem Borrell +

  • Hanmin Qin +

  • Hendrik Makait +

  • Hugues Valois

  • Hussain Tamboli +

  • Iva Miholic +

  • Jan Novotný +

  • Jan Rudolph

  • Jean Helie +

  • Jean-Baptiste Schiratti +

  • Jean-Mathieu Deschenes

  • Jeff Knupp +

  • Jeff Reback

  • Jeff Tratner

  • JennaVergeynst

  • JimStearns206

  • Joel Nothman

  • John W. O’Brien

  • Jon Crall +

  • Jon Mease

  • Jonathan J. Helmus +

  • Joris Van den Bossche

  • JosephWagner

  • Juarez Bochi

  • Julian Kuhlmann +

  • Karel De Brabandere

  • Kassandra Keeton +

  • Keiron Pizzey +

  • Keith Webber

  • Kernc

  • Kevin Sheppard

  • Kirk Hansen +

  • Licht Takeuchi +

  • Lucas Kushner +

  • Mahdi Ben Jelloul +

  • Makarov Andrey +

  • Malgorzata Turzanska +

  • Marc Garcia +

  • Margaret Sy +

  • MarsGuy +

  • Matt Bark +

  • Matthew Roeschke

  • Matti Picus

  • Mehmet Ali “Mali” Akmanalp

  • Michael Gasvoda +

  • Michael Penkov +

  • Milo +

  • Morgan Stuart +

  • Morgan243 +

  • Nathan Ford +

  • Nick Eubank

  • Nick Garvey +

  • Oleg Shteynbuk +

  • P-Tillmann +

  • Pankaj Pandey

  • Patrick Luo

  • Patrick O’Melveny

  • Paul Reidy +

  • Paula +

  • Peter Quackenbush

  • Peter Yanovich +

  • Phillip Cloud

  • Pierre Haessig

  • Pietro Battiston

  • Pradyumna Reddy Chinthala

  • Prasanjit Prakash

  • RobinFiveWords

  • Ryan Hendrickson

  • Sam Foo

  • Sangwoong Yoon +

  • Simon Gibbons +

  • SimonBaron

  • Steven Cutting +

  • Sudeep +

  • Sylvia +

  • T N +

  • Telt

  • Thomas A Caswell

  • Tim Swast +

  • Tom Augspurger

  • Tong SHEN

  • Tuan +

  • Utkarsh Upadhyay +

  • Vincent La +

  • Vivek +

  • WANG Aiyong

  • WBare

  • Wes McKinney

  • XF +

  • Yi Liu +

  • Yosuke Nakabayashi +

  • aaron315 +

  • abarber4gh +

  • aernlund +

  • agustín méndez +

  • andymaheshw +

  • ante328 +

  • aviolov +

  • bpraggastis

  • cbertinato +

  • cclauss +

  • chernrick

  • chris-b1

  • dkamm +

  • dwkenefick

  • economy

  • faic +

  • fding253 +

  • gfyoung

  • guygoldberg +

  • hhuuggoo +

  • huashuai +

  • ian

  • iulia +

  • jaredsnyder

  • jbrockmendel +

  • jdeschenes

  • jebob +

  • jschendel +

  • keitakurita

  • kernc +

  • kiwirob +

  • kjford

  • linebp

  • lloydkirk

  • louispotok +

  • majiang +

  • manikbhandari +

  • margotphoenix +

  • matthiashuschle +

  • mattip

  • mjlove12 +

  • nmartensen +

  • pandas-docs-bot +

  • parchd-1 +

  • philipphanemann +

  • rdk1024 +

  • reidy-p +

  • ri938

  • ruiann +

  • rvernica +

  • s-weigand +

  • scotthavard92 +

  • skwbc +

  • step4me +

  • tobycheese +

  • topper-123 +

  • tsdlovell

  • ysau +

  • zzgao +