0.23.0 版本新特性 (2018 年 5 月 15 日)#

这是继 0.22.0 之后的一个主要版本,包含了多项 API 变更、弃用、新功能、增强功能和性能改进,以及大量的 bug 修复。我们建议所有用户升级到此版本。

主要亮点包括

更新前请查阅 API 变更弃用

警告

从 2019 年 1 月 1 日起,pandas 的功能发布版本将只支持 Python 3。详情请参阅 取消支持 Python 2.7

新特性#

JSON 读/写:使用 orient='table' 支持往返#

现在,DataFrame 可以通过使用 orient='table' 参数写入 JSON 并随后读取回来,同时保留元数据(参见 GH 18912GH 9146)。此前,所有可用的 orient 值都无法保证保留 dtypes 和索引名等元数据。

In [1]: df = pd.DataFrame({'foo': [1, 2, 3, 4],
   ...:                    'bar': ['a', 'b', 'c', 'd'],
   ...:                    'baz': pd.date_range('2018-01-01', freq='d', periods=4),
   ...:                    'qux': pd.Categorical(['a', 'b', 'c', 'c'])},
   ...:                   index=pd.Index(range(4), name='idx'))
   ...: 

In [2]: df
Out[2]: 
     foo bar        baz qux
idx                        
0      1   a 2018-01-01   a
1      2   b 2018-01-02   b
2      3   c 2018-01-03   c
3      4   d 2018-01-04   c

[4 rows x 4 columns]

In [3]: df.dtypes
Out[3]: 
foo             int64
bar            object
baz    datetime64[ns]
qux          category
Length: 4, dtype: object

In [4]: df.to_json('test.json', orient='table')

In [5]: new_df = pd.read_json('test.json', orient='table')

In [6]: new_df
Out[6]: 
     foo bar        baz qux
idx                        
0      1   a 2018-01-01   a
1      2   b 2018-01-02   b
2      3   c 2018-01-03   c
3      4   d 2018-01-04   c

[4 rows x 4 columns]

In [7]: new_df.dtypes
Out[7]: 
foo             int64
bar            object
baz    datetime64[ns]
qux          category
Length: 4, dtype: object

请注意,该往返格式不支持字符串 index,因为 write_json 默认使用它来表示缺失的索引名。

In [8]: df.index.name = 'index'

In [9]: df.to_json('test.json', orient='table')

In [10]: new_df = pd.read_json('test.json', orient='table')

In [11]: new_df
Out[11]: 
   foo bar        baz qux
0    1   a 2018-01-01   a
1    2   b 2018-01-02   b
2    3   c 2018-01-03   c
3    4   d 2018-01-04   c

[4 rows x 4 columns]

In [12]: new_df.dtypes
Out[12]: 
foo             int64
bar            object
baz    datetime64[ns]
qux          category
Length: 4, dtype: object

方法 .assign() 接受依赖参数#

DataFrame.assign() 现在对于 Python 3.6 及更高版本接受依赖的关键字参数(另请参阅 PEP 468)。如果参数是可调用对象,后面的关键字参数现在可以引用前面的参数。请参阅此处文档GH 14207)。

In [13]: df = pd.DataFrame({'A': [1, 2, 3]})

In [14]: df
Out[14]: 
   A
0  1
1  2
2  3

[3 rows x 1 columns]

In [15]: df.assign(B=df.A, C=lambda x: x['A'] + x['B'])
Out[15]: 
   A  B  C
0  1  1  2
1  2  2  4
2  3  3  6

[3 rows x 3 columns]

警告

当您使用 .assign() 更新现有列时,这可能会微妙地改变代码的行为。以前,引用其他正在更新的变量的可调用对象会获取“旧”值。

以前的行为

In [2]: df = pd.DataFrame({"A": [1, 2, 3]})

In [3]: df.assign(A=lambda df: df.A + 1, C=lambda df: df.A * -1)
Out[3]:
   A  C
0  2 -1
1  3 -2
2  4 -3

新的行为

In [16]: df.assign(A=df.A + 1, C=lambda df: df.A * -1)
Out[16]: 
   A  C
0  2 -2
1  3 -3
2  4 -4

[3 rows x 2 columns]

支持基于列和索引级别的组合进行合并#

传递给 DataFrame.merge() 作为 onleft_onright_on 参数的字符串现在可以引用列名或索引级别名。这使得可以在不重置索引的情况下,基于索引级别和列的组合合并 DataFrame 实例。请参阅基于列和级别的合并文档部分。(GH 14355

In [17]: left_index = pd.Index(['K0', 'K0', 'K1', 'K2'], name='key1')

In [18]: left = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
   ....:                      'B': ['B0', 'B1', 'B2', 'B3'],
   ....:                      'key2': ['K0', 'K1', 'K0', 'K1']},
   ....:                     index=left_index)
   ....: 

In [19]: right_index = pd.Index(['K0', 'K1', 'K2', 'K2'], name='key1')

In [20]: right = pd.DataFrame({'C': ['C0', 'C1', 'C2', 'C3'],
   ....:                       'D': ['D0', 'D1', 'D2', 'D3'],
   ....:                       'key2': ['K0', 'K0', 'K0', 'K1']},
   ....:                      index=right_index)
   ....: 

In [21]: left.merge(right, on=['key1', 'key2'])
Out[21]: 
       A   B key2   C   D
key1                     
K0    A0  B0   K0  C0  D0
K1    A2  B2   K0  C1  D1
K2    A3  B3   K1  C3  D3

[3 rows x 5 columns]

支持基于列和索引级别的组合进行排序#

传递给 DataFrame.sort_values() 作为 by 参数的字符串现在可以引用列名或索引级别名。这使得可以在不重置索引的情况下,基于索引级别和列的组合对 DataFrame 实例进行排序。请参阅按索引和值排序文档部分。(GH 14353

# Build MultiIndex
In [22]: idx = pd.MultiIndex.from_tuples([('a', 1), ('a', 2), ('a', 2),
   ....:                                  ('b', 2), ('b', 1), ('b', 1)])
   ....: 

In [23]: idx.names = ['first', 'second']

# Build DataFrame
In [24]: df_multi = pd.DataFrame({'A': np.arange(6, 0, -1)},
   ....:                         index=idx)
   ....: 

In [25]: df_multi
Out[25]: 
              A
first second   
a     1       6
      2       5
      2       4
b     2       3
      1       2
      1       1

[6 rows x 1 columns]

# Sort by 'second' (index) and 'A' (column)
In [26]: df_multi.sort_values(by=['second', 'A'])
Out[26]: 
              A
first second   
b     1       1
      1       2
a     1       6
b     2       3
a     2       4
      2       5

[6 rows x 1 columns]

使用自定义类型扩展 pandas (实验性)#

pandas 现在支持将不一定是 1-D NumPy 数组的类数组对象存储为 DataFrame 中的列或 Series 中的值。这使得第三方库可以实现对 NumPy 类型的扩展,类似于 pandas 实现分类类型、带时区的日期时间、周期和间隔。

作为演示,我们将使用 cyberpandas,它提供了一个用于存储 IP 地址的 IPArray 类型。

In [1]: from cyberpandas import IPArray

In [2]: values = IPArray([
   ...:     0,
   ...:     3232235777,
   ...:     42540766452641154071740215577757643572
   ...: ])
   ...:
   ...:

IPArray 不是一个普通的 1-D NumPy 数组,但由于它是 pandas ExtensionArray,它可以正确地存储在 pandas 的容器中。

In [3]: ser = pd.Series(values)

In [4]: ser
Out[4]:
0                         0.0.0.0
1                     192.168.1.1
2    2001:db8:85a3::8a2e:370:7334
dtype: ip

注意 dtype 是 ip。底层数组的缺失值语义得到了遵守。

In [5]: ser.isna()
Out[5]:
0     True
1    False
2    False
dtype: bool

更多信息请参阅扩展类型文档。如果您构建了一个扩展数组,请在生态系统页面上宣传它。

新关键字 observed 用于在 GroupBy 中排除未观察到的类别#

按分类类型分组会包含输出中未观察到的类别。当按多个分类列分组时,这意味着您将获得所有类别的笛卡尔积,包括没有观察值的组合,这可能导致大量的组。我们添加了一个关键字 observed 来控制此行为,为了向后兼容,它默认为 observed=False。(GH 14942, GH 8138, GH 15217, GH 17594, GH 8669, GH 20583, GH 20902

In [27]: cat1 = pd.Categorical(["a", "a", "b", "b"],
   ....:                       categories=["a", "b", "z"], ordered=True)
   ....: 

In [28]: cat2 = pd.Categorical(["c", "d", "c", "d"],
   ....:                       categories=["c", "d", "y"], ordered=True)
   ....: 

In [29]: df = pd.DataFrame({"A": cat1, "B": cat2, "values": [1, 2, 3, 4]})

In [30]: df['C'] = ['foo', 'bar'] * 2

In [31]: df
Out[31]: 
   A  B  values    C
0  a  c       1  foo
1  a  d       2  bar
2  b  c       3  foo
3  b  d       4  bar

[4 rows x 4 columns]

显示所有值(以前的行为)

In [32]: df.groupby(['A', 'B', 'C'], observed=False).count()
Out[32]: 
         values
A B C          
a c bar       0
    foo       1
  d bar       1
    foo       0
  y bar       0
...         ...
z c foo       0
  d bar       0
    foo       0
  y bar       0
    foo       0

[18 rows x 1 columns]

只显示观察到的值

In [33]: df.groupby(['A', 'B', 'C'], observed=True).count()
Out[33]: 
         values
A B C          
a c foo       1
  d bar       1
b c foo       1
  d bar       1

[4 rows x 1 columns]

对于透视操作,此行为已经dropna 关键字控制。

In [34]: cat1 = pd.Categorical(["a", "a", "b", "b"],
   ....:                       categories=["a", "b", "z"], ordered=True)
   ....: 

In [35]: cat2 = pd.Categorical(["c", "d", "c", "d"],
   ....:                       categories=["c", "d", "y"], ordered=True)
   ....: 

In [36]: df = pd.DataFrame({"A": cat1, "B": cat2, "values": [1, 2, 3, 4]})

In [37]: df
Out[37]: 
   A  B  values
0  a  c       1
1  a  d       2
2  b  c       3
3  b  d       4

[4 rows x 3 columns]
In [1]: pd.pivot_table(df, values='values', index=['A', 'B'], dropna=True)

Out[1]:
     values
A B
a c     1.0
  d     2.0
b c     3.0
  d     4.0

In [2]: pd.pivot_table(df, values='values', index=['A', 'B'], dropna=False)

Out[2]:
     values
A B
a c     1.0
  d     2.0
  y     NaN
b c     3.0
  d     4.0
  y     NaN
z c     NaN
  d     NaN
  y     NaN

Rolling/Expanding.apply() 接受 raw=False 以将 Series 传递给函数#

Series.rolling().apply()DataFrame.rolling().apply()Series.expanding().apply()DataFrame.expanding().apply() 新增了 raw=None 参数。这类似于 DataFame.apply()。如果此参数为 True,则可以将 np.ndarray 发送到应用函数。如果为 False,则将传递一个 Series。默认值为 None,这保留了向后兼容性,因此默认将为 True,发送一个 np.ndarray。在未来版本中,默认值将更改为 False,发送一个 Series。(GH 5071, GH 20584

In [38]: s = pd.Series(np.arange(5), np.arange(5) + 1)

In [39]: s
Out[39]: 
1    0
2    1
3    2
4    3
5    4
Length: 5, dtype: int64

传递一个 Series

In [40]: s.rolling(2, min_periods=1).apply(lambda x: x.iloc[-1], raw=False)
Out[40]: 
1    0.0
2    1.0
3    2.0
4    3.0
5    4.0
Length: 5, dtype: float64

模仿原始行为,传递一个 ndarray

In [41]: s.rolling(2, min_periods=1).apply(lambda x: x[-1], raw=True)
Out[41]: 
1    0.0
2    1.0
3    2.0
4    3.0
5    4.0
Length: 5, dtype: float64

DataFrame.interpolate 新增 limit_area kwarg#

DataFrame.interpolate() 新增了 limit_area 参数,以进一步控制替换哪些 NaN。使用 limit_area='inside' 只填充被有效值包围的 NaN,或使用 limit_area='outside' 只填充现有有效值外部的 NaN,同时保留内部的 NaN。(GH 16284)请参阅此处完整文档

In [42]: ser = pd.Series([np.nan, np.nan, 5, np.nan, np.nan,
   ....:                  np.nan, 13, np.nan, np.nan])
   ....: 

In [43]: ser
Out[43]: 
0     NaN
1     NaN
2     5.0
3     NaN
4     NaN
5     NaN
6    13.0
7     NaN
8     NaN
Length: 9, dtype: float64

在两个方向上填充一个连续的内部值

In [44]: ser.interpolate(limit_direction='both', limit_area='inside', limit=1)
Out[44]: 
0     NaN
1     NaN
2     5.0
3     7.0
4     NaN
5    11.0
6    13.0
7     NaN
8     NaN
Length: 9, dtype: float64

向后填充所有连续的外部值

In [45]: ser.interpolate(limit_direction='backward', limit_area='outside')
Out[45]: 
0     5.0
1     5.0
2     5.0
3     NaN
4     NaN
5     NaN
6    13.0
7     NaN
8     NaN
Length: 9, dtype: float64

在两个方向上填充所有连续的外部值

In [46]: ser.interpolate(limit_direction='both', limit_area='outside')
Out[46]: 
0     5.0
1     5.0
2     5.0
3     NaN
4     NaN
5     NaN
6    13.0
7    13.0
8    13.0
Length: 9, dtype: float64

函数 get_dummies 现在支持 dtype 参数#

get_dummies() 现在接受 dtype 参数,用于指定新列的数据类型。默认值仍为 uint8。(GH 18330

In [47]: df = pd.DataFrame({'a': [1, 2], 'b': [3, 4], 'c': [5, 6]})

In [48]: pd.get_dummies(df, columns=['c']).dtypes
Out[48]: 
a      int64
b      int64
c_5     bool
c_6     bool
Length: 4, dtype: object

In [49]: pd.get_dummies(df, columns=['c'], dtype=bool).dtypes
Out[49]: 
a      int64
b      int64
c_5     bool
c_6     bool
Length: 4, dtype: object

Timedelta 取模方法#

当与类 Timedelta 对象或数值参数一起操作时,Timedelta 对象现在定义了 mod (%) 和 divmod 操作。请参阅此处文档。(GH 19365

In [50]: td = pd.Timedelta(hours=37)

In [51]: td % pd.Timedelta(minutes=45)
Out[51]: Timedelta('0 days 00:15:00')

方法 .rank() 在存在 NaN 值时处理 inf#

在以前的版本中,.rank() 会将 inf 元素的排名分配为 NaN。现在排名计算正确。(GH 6945

In [52]: s = pd.Series([-np.inf, 0, 1, np.nan, np.inf])

In [53]: s
Out[53]: 
0   -inf
1    0.0
2    1.0
3    NaN
4    inf
Length: 5, dtype: float64

以前的行为

In [11]: s.rank()
Out[11]:
0    1.0
1    2.0
2    3.0
3    NaN
4    NaN
dtype: float64

当前行为

In [54]: s.rank()
Out[54]: 
0    1.0
1    2.0
2    3.0
3    NaN
4    4.0
Length: 5, dtype: float64

此外,以前如果您将 inf-inf 值与 NaN 值一起排名时,使用 'top' 或 'bottom' 参数时计算不会区分 NaN 和无穷大。

In [55]: s = pd.Series([np.nan, np.nan, -np.inf, -np.inf])

In [56]: s
Out[56]: 
0    NaN
1    NaN
2   -inf
3   -inf
Length: 4, dtype: float64

以前的行为

In [15]: s.rank(na_option='top')
Out[15]:
0    2.5
1    2.5
2    2.5
3    2.5
dtype: float64

当前行为

In [57]: s.rank(na_option='top')
Out[57]: 
0    1.5
1    1.5
2    3.5
3    3.5
Length: 4, dtype: float64

这些 bug 已被修复

Series.str.cat 新增 join kwarg#

以前,Series.str.cat() 与大多数 pandas 的行为不同,它在连接前不会根据索引对 Series 进行对齐(参见 GH 18657)。该方法现在新增了一个关键字 join 来控制对齐方式,请参见下面的示例和此处

在 v0.23 版本中,join 默认为 None(表示不对齐),但在未来的 pandas 版本中,此默认值将更改为 'left'

In [58]: s = pd.Series(['a', 'b', 'c', 'd'])

In [59]: t = pd.Series(['b', 'd', 'e', 'c'], index=[1, 3, 4, 2])

In [60]: s.str.cat(t)
Out[60]: 
0    NaN
1     bb
2     cc
3     dd
Length: 4, dtype: object

In [61]: s.str.cat(t, join='left', na_rep='-')
Out[61]: 
0    a-
1    bb
2    cc
3    dd
Length: 4, dtype: object

此外,Series.str.cat() 现在也适用于 CategoricalIndex(以前会引发 ValueError;参见 GH 20842)。

DataFrame.astype 支持按列转换为 Categorical 类型#

DataFrame.astype() 现在可以通过提供字符串 'category'CategoricalDtype 来执行按列转换为 Categorical 类型。以前,尝试这样做会引发 NotImplementedError。更多详情和示例请参阅文档的对象创建部分。(GH 12860, GH 18099

提供字符串 'category' 将执行按列转换,只有在给定列中出现的标签才被设置为类别。

In [62]: df = pd.DataFrame({'A': list('abca'), 'B': list('bccd')})

In [63]: df = df.astype('category')

In [64]: df['A'].dtype
Out[64]: CategoricalDtype(categories=['a', 'b', 'c'], ordered=False, categories_dtype=object)

In [65]: df['B'].dtype
Out[65]: CategoricalDtype(categories=['b', 'c', 'd'], ordered=False, categories_dtype=object)

提供 CategoricalDtype 将使每列中的类别与提供的 dtype 一致。

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

In [67]: df = pd.DataFrame({'A': list('abca'), 'B': list('bccd')})

In [68]: cdt = CategoricalDtype(categories=list('abcd'), ordered=True)

In [69]: df = df.astype(cdt)

In [70]: df['A'].dtype
Out[70]: CategoricalDtype(categories=['a', 'b', 'c', 'd'], ordered=True, categories_dtype=object)

In [71]: df['B'].dtype
Out[71]: CategoricalDtype(categories=['a', 'b', 'c', 'd'], ordered=True, categories_dtype=object)

其他增强功能#

在 Python 3.6+ 中,从字典实例化将保留字典的插入顺序#

在 Python 3.6 之前,Python 中的字典没有正式定义的顺序。对于 Python 3.6 及更高版本,字典按插入顺序排序,参见 PEP 468。当您使用 Python 3.6 或更高版本并从字典创建 SeriesDataFrame 时,pandas 将使用字典的插入顺序。(GH 19884)

之前的行为(以及 Python < 3.6 时的当前行为)

In [16]: pd.Series({'Income': 2000,
   ....:            'Expenses': -1500,
   ....:            'Taxes': -200,
   ....:            'Net result': 300})
Out[16]:
Expenses     -1500
Income        2000
Net result     300
Taxes         -200
dtype: int64

请注意,上面的 Series 按索引值按字母顺序排序。

新的行为(适用于 Python >= 3.6)

In [72]: pd.Series({'Income': 2000,
   ....:            'Expenses': -1500,
   ....:            'Taxes': -200,
   ....:            'Net result': 300})
   ....: 
Out[72]: 
Income        2000
Expenses     -1500
Taxes         -200
Net result     300
Length: 4, dtype: int64

注意 Series 现在按插入顺序排序。此新行为适用于所有相关的 pandas 类型(SeriesDataFrameSparseSeriesSparseDataFrame)。

如果您希望在使用 Python >= 3.6 时保留旧行为,可以使用 .sort_index()

In [73]: pd.Series({'Income': 2000,
   ....:            'Expenses': -1500,
   ....:            'Taxes': -200,
   ....:            'Net result': 300}).sort_index()
   ....: 
Out[73]: 
Expenses     -1500
Income        2000
Net result     300
Taxes         -200
Length: 4, dtype: int64

弃用 Panel#

Panel 在 0.20.x 版本中被弃用,显示为 DeprecationWarning。现在使用 Panel 将显示 FutureWarning。表示 3 维数据的推荐方法是通过 to_frame() 方法在 DataFrame 上使用 MultiIndex,或使用 xarray package。pandas 提供了一个 to_xarray() 方法来自动化此转换 (GH 13563, GH 18324)。

In [75]: import pandas._testing as tm

In [76]: p = tm.makePanel()

In [77]: p
Out[77]:
<class 'pandas.core.panel.Panel'>
Dimensions: 3 (items) x 3 (major_axis) x 4 (minor_axis)
Items axis: ItemA to ItemC
Major_axis axis: 2000-01-03 00:00:00 to 2000-01-05 00:00:00
Minor_axis axis: A to D

转换为 MultiIndex DataFrame

In [78]: p.to_frame()
Out[78]:
                     ItemA     ItemB     ItemC
major      minor
2000-01-03 A      0.469112  0.721555  0.404705
           B     -1.135632  0.271860 -1.039268
           C      0.119209  0.276232 -1.344312
           D     -2.104569  0.113648 -0.109050
2000-01-04 A     -0.282863 -0.706771  0.577046
           B      1.212112 -0.424972 -0.370647
           C     -1.044236 -1.087401  0.844885
           D     -0.494929 -1.478427  1.643563
2000-01-05 A     -1.509059 -1.039575 -1.715002
           B     -0.173215  0.567020 -1.157892
           C     -0.861849 -0.673690  1.075770
           D      1.071804  0.524988 -1.469388

[12 rows x 3 columns]

转换为 xarray DataArray

In [79]: p.to_xarray()
Out[79]:
<xarray.DataArray (items: 3, major_axis: 3, minor_axis: 4)>
array([[[ 0.469112, -1.135632,  0.119209, -2.104569],
        [-0.282863,  1.212112, -1.044236, -0.494929],
        [-1.509059, -0.173215, -0.861849,  1.071804]],

       [[ 0.721555,  0.27186 ,  0.276232,  0.113648],
        [-0.706771, -0.424972, -1.087401, -1.478427],
        [-1.039575,  0.56702 , -0.67369 ,  0.524988]],

       [[ 0.404705, -1.039268, -1.344312, -0.10905 ],
        [ 0.577046, -0.370647,  0.844885,  1.643563],
        [-1.715002, -1.157892,  1.07577 , -1.469388]]])
Coordinates:
  * items       (items) object 'ItemA' 'ItemB' 'ItemC'
  * major_axis  (major_axis) datetime64[ns] 2000-01-03 2000-01-04 2000-01-05
  * minor_axis  (minor_axis) object 'A' 'B' 'C' 'D'

移除 pandas.core.common#

以下错误和警告消息已从 pandas.core.common 中移除 (GH 13634, GH 19769)

  • PerformanceWarning

  • UnsupportedFunctionCall

  • UnsortedIndexError

  • AbstractMethodError

这些可以从 pandas.errors 中导入(自 0.19.0 版本起)。

使 DataFrame.apply 输出一致的更改#

DataFrame.apply() 在应用返回 list-like 对象且 axis=1 的任意用户定义函数时存在不一致。现已解决了一些错误和不一致之处。如果应用的函数返回 Series,则 pandas 将返回 DataFrame;否则将返回 Series,这包括返回 list-like 对象(例如 tuplelist)的情况 (GH 16353, GH 17437, GH 17970, GH 17348, GH 17892, GH 18573, GH 17602, GH 18775, GH 18901, GH 18919)。

In [74]: df = pd.DataFrame(np.tile(np.arange(3), 6).reshape(6, -1) + 1,
   ....:                   columns=['A', 'B', 'C'])
   ....: 

In [75]: df
Out[75]: 
   A  B  C
0  1  2  3
1  1  2  3
2  1  2  3
3  1  2  3
4  1  2  3
5  1  2  3

[6 rows x 3 columns]

之前的行为:如果返回的形状恰好与原始列的长度匹配,则会返回 DataFrame。如果返回的形状不匹配,则返回包含列表的 Series

In [3]: df.apply(lambda x: [1, 2, 3], axis=1)
Out[3]:
   A  B  C
0  1  2  3
1  1  2  3
2  1  2  3
3  1  2  3
4  1  2  3
5  1  2  3

In [4]: df.apply(lambda x: [1, 2], axis=1)
Out[4]:
0    [1, 2]
1    [1, 2]
2    [1, 2]
3    [1, 2]
4    [1, 2]
5    [1, 2]
dtype: object

新的行为:当应用的函数返回 list-like 对象时,现在将 *始终* 返回 Series

In [76]: df.apply(lambda x: [1, 2, 3], axis=1)
Out[76]: 
0    [1, 2, 3]
1    [1, 2, 3]
2    [1, 2, 3]
3    [1, 2, 3]
4    [1, 2, 3]
5    [1, 2, 3]
Length: 6, dtype: object

In [77]: df.apply(lambda x: [1, 2], axis=1)
Out[77]: 
0    [1, 2]
1    [1, 2]
2    [1, 2]
3    [1, 2]
4    [1, 2]
5    [1, 2]
Length: 6, dtype: object

要展开列,可以使用 result_type='expand'

In [78]: df.apply(lambda x: [1, 2, 3], axis=1, result_type='expand')
Out[78]: 
   0  1  2
0  1  2  3
1  1  2  3
2  1  2  3
3  1  2  3
4  1  2  3
5  1  2  3

[6 rows x 3 columns]

要将结果广播到原始列(长度正确的 list-like 对象的旧行为),可以使用 result_type='broadcast'。形状必须与原始列匹配。

In [79]: df.apply(lambda x: [1, 2, 3], axis=1, result_type='broadcast')
Out[79]: 
   A  B  C
0  1  2  3
1  1  2  3
2  1  2  3
3  1  2  3
4  1  2  3
5  1  2  3

[6 rows x 3 columns]

返回 Series 允许控制确切的返回结构和列名

In [80]: df.apply(lambda x: pd.Series([1, 2, 3], index=['D', 'E', 'F']), axis=1)
Out[80]: 
   D  E  F
0  1  2  3
1  1  2  3
2  1  2  3
3  1  2  3
4  1  2  3
5  1  2  3

[6 rows x 3 columns]

连接将不再排序#

在 pandas 的未来版本中,当非连接轴未对齐时,pandas.concat() 将不再对其进行排序。当前行为与之前相同(排序),但现在当未指定 sort 且非连接轴未对齐时,会发出警告 (GH 4588)。

In [81]: df1 = pd.DataFrame({"a": [1, 2], "b": [1, 2]}, columns=['b', 'a'])

In [82]: df2 = pd.DataFrame({"a": [4, 5]})

In [83]: pd.concat([df1, df2])
Out[83]: 
     b  a
0  1.0  1
1  2.0  2
0  NaN  4
1  NaN  5

[4 rows x 2 columns]

要保留之前的行为(排序)并抑制警告,请传递 sort=True

In [84]: pd.concat([df1, df2], sort=True)
Out[84]: 
   a    b
0  1  1.0
1  2  2.0
0  4  NaN
1  5  NaN

[4 rows x 2 columns]

要接受未来的行为(不排序),请传递 sort=False

请注意,此更改也适用于 DataFrame.append(),后者也新增了 sort 关键字来控制此行为。

构建更改#

  • 现在构建用于开发的 pandas 需要 cython >= 0.24 (GH 18613)

  • 现在从源代码构建时在 setup.py 中明确要求 setuptools (GH 18113)

  • 更新了 conda recipe,使其符合 conda-build 3.0+ (GH 18002)

Index 除以零正确填充#

Index 及其子类执行除法运算时,正数除以零现在将填充 np.inf,负数除以零填充 -np.inf,以及 0 / 0 填充 np.nan。这与现有的 Series 行为一致。(GH 19322, GH 19347)

以前的行为

In [6]: index = pd.Int64Index([-1, 0, 1])

In [7]: index / 0
Out[7]: Int64Index([0, 0, 0], dtype='int64')

# Previous behavior yielded different results depending on the type of zero in the divisor
In [8]: index / 0.0
Out[8]: Float64Index([-inf, nan, inf], dtype='float64')

In [9]: index = pd.UInt64Index([0, 1])

In [10]: index / np.array([0, 0], dtype=np.uint64)
Out[10]: UInt64Index([0, 0], dtype='uint64')

In [11]: pd.RangeIndex(1, 5) / 0
ZeroDivisionError: integer division or modulo by zero

当前行为

In [12]: index = pd.Int64Index([-1, 0, 1])
# division by zero gives -infinity where negative,
# +infinity where positive, and NaN for 0 / 0
In [13]: index / 0

# The result of division by zero should not depend on
# whether the zero is int or float
In [14]: index / 0.0

In [15]: index = pd.UInt64Index([0, 1])
In [16]: index / np.array([0, 0], dtype=np.uint64)

In [17]: pd.RangeIndex(1, 5) / 0

从字符串中提取匹配模式#

默认情况下,使用 str.extract() 从字符串中提取匹配模式时,如果只提取一个组,则返回 Series(如果提取多个组,则返回 DataFrame)。从 pandas 0.23.0 开始,str.extract() 始终返回 DataFrame,除非将 expand 设置为 False。最后,None 曾经是 expand 参数的可接受值(等同于 False),但现在会引发 ValueError。(GH 11386

以前的行为

In [1]: s = pd.Series(['number 10', '12 eggs'])

In [2]: extracted = s.str.extract(r'.*(\d\d).*')

In [3]: extracted
Out [3]:
0    10
1    12
dtype: object

In [4]: type(extracted)
Out [4]:
pandas.core.series.Series

新的行为

In [85]: s = pd.Series(['number 10', '12 eggs'])

In [86]: extracted = s.str.extract(r'.*(\d\d).*')

In [87]: extracted
Out[87]: 
    0
0  10
1  12

[2 rows x 1 columns]

In [88]: type(extracted)
Out[88]: pandas.core.frame.DataFrame

要恢复先前的行为,只需将 expand 设置为 False

In [89]: s = pd.Series(['number 10', '12 eggs'])

In [90]: extracted = s.str.extract(r'.*(\d\d).*', expand=False)

In [91]: extracted
Out[91]: 
0    10
1    12
Length: 2, dtype: object

In [92]: type(extracted)
Out[92]: pandas.core.series.Series

CategoricalDtypeordered 参数的默认值#

CategoricalDtypeordered 参数的默认值已从 False 更改为 None,以允许更新 categories 而不影响 ordered。对于下游对象(例如 Categorical),行为应保持一致。(GH 18790

在以前的版本中,ordered 参数的默认值为 False。当用户尝试更新 categories 时,如果未明确指定 ordered,它会静默地默认为 False,这可能导致 ordered 参数意外地从 True 更改为 Falseordered=None 的新行为是保留 ordered 的现有值。

新的行为

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

In [3]: cat = pd.Categorical(list('abcaba'), ordered=True, categories=list('cba'))

In [4]: cat
Out[4]:
[a, b, c, a, b, a]
Categories (3, object): [c < b < a]

In [5]: cdt = CategoricalDtype(categories=list('cbad'))

In [6]: cat.astype(cdt)
Out[6]:
[a, b, c, a, b, a]
Categories (4, object): [c < b < a < d]

请注意,在上面的示例中,转换后的 Categorical 保留了 ordered=True。如果 ordered 的默认值保持为 False,则转换后的 Categorical 将变为无序,尽管从未明确指定 ordered=False。要更改 ordered 的值,请将其明确传递给新的 dtype,例如 CategoricalDtype(categories=list('cbad'), ordered=False)

请注意,上面讨论的 ordered 的意外转换在早期版本中并未出现,原因是由于阻止 astype 进行任何类别的到类别转换的独立错误(GH 10696GH 18593)。这些错误在此版本中已修复,并促使更改了 ordered 的默认值。

更好的终端 DataFrame 美观打印#

以前,最大列数的默认值是 pd.options.display.max_columns=20。这意味着相对较宽的数据帧无法在终端宽度内显示,pandas 会引入换行符来显示这 20 列。这导致输出相对难以阅读

../_images/print_df_old.png

如果 Python 在终端中运行,现在会自动确定最大列数,以便打印的数据帧适合当前终端宽度(pd.options.display.max_columns=0)(GH 17023)。如果 Python 作为 Jupyter 内核(例如 Jupyter QtConsole 或 Jupyter notebook,以及许多 IDE)运行,则无法自动推断此值,因此设置为 20,与早期版本一样。在终端中,这会产生更好的输出

../_images/print_df_new.png

请注意,如果您不喜欢新的默认设置,可以随时自行设置此选项。要恢复旧设置,可以运行以下行

pd.options.display.max_columns = 20

日期时间类 API 更改#

  • Timedelta 默认构造函数现在接受 ISO 8601 Duration 字符串作为参数(GH 19040

  • dtype='datetime64[ns]'Series 中减去 NaT 会返回 dtype='timedelta64[ns]'Series,而不是 dtype='datetime64[ns]'GH 18808

  • TimedeltaIndex 中添加或减去 NaT 将返回 TimedeltaIndex 而不是 DatetimeIndexGH 19124

  • 当索引对象的频率是 None 时,DatetimeIndex.shift()TimedeltaIndex.shift() 现在会引发 NullFrequencyError(它是 ValueError 的子类,在早期版本中会引发 ValueError)(GH 19147

  • dtype='timedelta64[ns]'Series 中添加或减去 NaN 将引发 TypeError,而不是将 NaN 视为 NaTGH 19274

  • NaTdatetime.timedelta 进行除法运算现在将返回 NaN,而不是引发异常(GH 17876

  • 具有 dtype='datetime64[ns]'SeriesPeriodIndex 之间的运算将正确地引发 TypeErrorGH 18850

  • 具有时区感知 dtype='datetime64[ns]'Series 与时区不匹配的 Series 之间的减法将引发 TypeError,而不是 ValueErrorGH 18817

  • Timestamp 不再静默忽略未使用或无效的 tztzinfo 关键字参数(GH 17690

  • Timestamp 不再静默忽略无效的 freq 参数(GH 5168

  • CacheableOffsetWeekDay 不再在 pandas.tseries.offsets 模块中可用(GH 17830

  • pandas.tseries.frequencies.get_freq_group()pandas.tseries.frequencies.DAYS 已从公共 API 中移除(GH 18034

  • Series.truncate()DataFrame.truncate() 如果索引未排序,将引发 ValueError,而不是无用的 KeyErrorGH 17935

  • 当索引不是 DatetimeIndex 时,Series.firstDataFrame.first 现在会引发 TypeError,而不是 NotImplementedErrorGH 20725)。

  • 当索引不是 DatetimeIndex 时,Series.lastDataFrame.last 现在会引发 TypeError,而不是 NotImplementedErrorGH 20725)。

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

  • pandas.merge() 在尝试合并时区感知和时区不感知列时提供更具信息量的错误消息(GH 15800

  • 对于 freq=NoneDatetimeIndexTimedeltaIndex,添加或减去整数 dtype 数组或 Index 将引发 NullFrequencyError,而不是 TypeErrorGH 19895

  • Timestamp 构造函数现在接受 nanosecond 关键字或位置参数(GH 18898

  • 在实例化后设置 DatetimeIndextz 属性时,现在将引发 AttributeErrorGH 3746

  • 具有 pytz 时区的 DatetimeIndex 现在将返回一致的 pytz 时区(GH 18595

其他 API 更改#

  • Series.astype()Index.astype() 使用不兼容的 dtype 时,现在会引发 TypeError,而不是 ValueErrorGH 18231

  • 使用对象 dtype 的时区感知 datetime 和指定了 dtype=object 构建 Series 时,现在将返回对象 dtype 的 Series,以前会推断 datetime dtype(GH 18231

  • 从空 dict 构建的 dtype=categorySeries 现在将具有 dtype=object 的 categories,而不是 dtype=float64,这与传递空列表的情况一致(GH 18515

  • MultiIndex 中所有为 NaN 的 level 现在被分配 float dtype,而不是 object,从而与 Index 保持一致(GH 17929)。

  • MultiIndex 的 level 名称(非 None 时)现在要求是唯一的:尝试创建带有重复名称的 MultiIndex 将引发 ValueErrorGH 18872

  • 使用不可哈希的 name/names 构建和重命名 Index/MultiIndex 现在将引发 TypeErrorGH 20527

  • Index.map() 现在可以接受 Series 和 dictionary 输入对象(GH 12756GH 18482GH 18509)。

  • DataFrame.unstack() 现在默认为 object 列填充 np.nan。(GH 12815

  • IntervalIndex 构造函数如果在输入数据的推断闭合方式与 closed 参数冲突时将引发异常(GH 18421

  • 向索引插入缺失值现在适用于所有类型的索引,并且无论传入的类型如何,都会自动插入正确类型的缺失值(NaNNaT 等)(GH 18295

  • 使用重复标签创建 MultiIndex 时,现在会引发 ValueError。(GH 17464

  • Series.fillna() 在将列表、元组或 DataFrame 作为 value 传递时,现在会引发 TypeError,而不是 ValueErrorGH 18293

  • pandas.DataFrame.merge() 在合并 intfloat 列时,不再将 float 列转换为 objectGH 16572

  • pandas.merge() 在尝试合并不兼容的数据类型时,现在会引发 ValueErrorGH 9780

  • UInt64Index 的默认 NA 值已从 0 更改为 NaN,这会影响使用 NA 进行屏蔽的方法,例如 UInt64Index.where()GH 18398

  • 重构了 setup.py,使用 find_packages 而不是明确列出所有子包(GH 18535

  • 重新排列了 read_excel() 中的关键字参数顺序,以与 read_csv() 对齐(GH 16672

  • wide_to_long() 以前将数字类后缀保留为 object dtype。现在如果可能,会将它们转换为数字(GH 17627

  • read_excel() 中,comment 参数现在作为命名参数公开(GH 18735

  • 重新排列了 read_excel() 中的关键字参数顺序,以与 read_csv() 对齐(GH 16672

  • 选项 html.bordermode.use_inf_as_null 在早期版本中已被弃用,现在它们将显示 FutureWarning,而不是 DeprecationWarningGH 19003

  • IntervalIndexIntervalDtype 不再支持 categorical、object 和 string 子类型(GH 19016

  • 无论子类型如何,IntervalDtype 现在与 'interval' 比较时返回 True;无论子类型如何,IntervalDtype.name 现在返回 'interval'GH 18980

  • drop()drop()drop()drop() 中删除具有重复项的轴中的不存在元素时,现在会引发 KeyError,而不是 ValueErrorGH 19186

  • Series.to_csv() 现在接受一个 compression 参数,其工作方式与 DataFrame.to_csv() 中的 compression 参数相同(GH 18958

  • IntervalIndex 与不兼容索引类型之间的集合运算(并集、差集等)现在会引发 TypeError,而不是 ValueErrorGH 19329

  • DateOffset 对象现在以更简单的方式呈现,例如 <DateOffset: days=1> 而不是 <DateOffset: kwds={'days': 1}>GH 19403

  • Categorical.fillna 现在验证其 valuemethod 关键字参数。当同时指定或都不指定时,现在会引发异常,这与 Series.fillna() 的行为一致(GH 19682

  • pd.to_datetime('today') 现在返回一个 datetime 对象,这与 pd.Timestamp('today') 一致;以前 pd.to_datetime('today') 返回一个 .normalized() datetime 对象(GH 19935

  • Series.str.replace() 现在接受一个可选的 regex 关键字参数,当设置为 False 时,使用字面字符串替换而不是正则表达式替换(GH 16808

  • DatetimeIndex.strftime()PeriodIndex.strftime() 现在返回一个 Index 而不是一个 numpy 数组,以与类似的访问器保持一致 (GH 20127)

  • 当指定更长的索引时,从长度为 1 的列表构造 Series 不再广播该列表 (GH 19714, GH 20391)。

  • 对于只包含 int 和 float 列的 DataFrame,DataFrame.to_dict() 在使用 orient='index' 时不再将 int 列转换为 float (GH 18580)

  • 传递给 Series.rolling().aggregate()DataFrame.rolling().aggregate() 或其扩展版本 (`expanding`) 的用户自定义函数现在将**始终**传递一个 Series,而不是 np.array.apply() 只有 raw 关键字,请参阅此处。这与 pandas 中 .aggregate() 的签名保持一致 (GH 20584)

  • Rolling 和 Expanding 类型在迭代时引发 NotImplementedError (GH 11704)。

弃用#

  • Series.from_arraySparseSeries.from_array 已弃用。请改用普通的构造函数 Series(..)SparseSeries(..) (GH 18213)。

  • DataFrame.as_matrix 已弃用。请改用 DataFrame.values (GH 18458)。

  • Series.asobjectDatetimeIndex.asobjectPeriodIndex.asobjectTimeDeltaIndex.asobject 已弃用。请改用 .astype(object) (GH 18572)

  • 现在按键的元组进行分组会发出 FutureWarning 并已弃用。将来,传递给 'by' 的元组将始终引用一个实际的元组作为单个键,而不是将元组视为多个键。要保留以前的行为,请使用列表而不是元组 (GH 18314)

  • Series.valid 已弃用。请改用 Series.dropna() (GH 18800)。

  • read_excel() 已弃用 skip_footer 参数。请改用 skipfooter (GH 18836)

  • 为了与 read_excel() 保持一致,ExcelFile.parse() 已弃用 sheetname,推荐使用 sheet_name (GH 20920)。

  • is_copy 属性已弃用,并将在未来的版本中移除 (GH 18801)。

  • IntervalIndex.from_intervals 已弃用,推荐使用 IntervalIndex 构造函数 (GH 19263)

  • DataFrame.from_items 已弃用。请改用 DataFrame.from_dict(),如果需要保留键的顺序,请使用 DataFrame.from_dict(OrderedDict()) (GH 17320, GH 17312)

  • 使用包含一些缺失键的列表对 MultiIndexFloatIndex 进行索引现在将显示 FutureWarning,这与其他类型的索引一致 (GH 17758)。

  • .apply()broadcast 参数已弃用,推荐使用 result_type='broadcast' (GH 18577)

  • .apply()reduce 参数已弃用,推荐使用 result_type='reduce' (GH 18577)

  • factorize()order 参数已弃用,并将在未来的版本中移除 (GH 19727)

  • Timestamp.weekday_nameDatetimeIndex.weekday_nameSeries.dt.weekday_name 已弃用,推荐使用 Timestamp.day_name()DatetimeIndex.day_name()Series.dt.day_name() (GH 12806)

  • pandas.tseries.plotting.tsplot 已弃用。请改用 Series.plot() (GH 18627)

  • Index.summary() 已弃用,并将在未来的版本中移除 (GH 18217)

  • NDFrame.get_ftype_counts() 已弃用,并将在未来的版本中移除 (GH 18243)

  • DataFrame.to_records() 中的 convert_datetime64 参数已弃用,并将在未来的版本中移除。导致引入此参数的 NumPy 错误已解决。此参数的默认值也已从 True 更改为 None (GH 18160)。

  • Series.rolling().apply()DataFrame.rolling().apply()Series.expanding().apply()DataFrame.expanding().apply() 已弃用默认传递 np.array 的行为。现在需要传递新的 raw 参数来明确指定传递的内容 (GH 20584)

  • SeriesIndex 类的 databasestridesflagsitemsize 属性已弃用,并将在未来的版本中移除 (GH 20419)。

  • DatetimeIndex.offset 已弃用。请改用 DatetimeIndex.freq (GH 20716)

  • 整数 ndarray 与 Timedelta 之间的整除已弃用。请改用 Timedelta.value 进行除法 (GH 19761)

  • 设置 PeriodIndex.freq(以前不能保证正确工作)已弃用。请改用 PeriodIndex.asfreq() (GH 20678)

  • Index.get_duplicates() 已弃用,并将在未来的版本中移除 (GH 20239)

  • Categorical.take 中负索引的先前默认行为已弃用。未来的版本中,其含义将从表示缺失值变为表示从右侧开始的位置索引。未来的行为与 Series.take() 一致 (GH 20664)。

  • DataFrame.dropna() 中向 axis 参数传递多个轴已弃用,并将在未来的版本中移除 (GH 20987)

移除先前版本的弃用/变更#

  • 针对过时用法 Categorical(codes, categories) 的警告(例如当 Categorical() 的前两个参数具有不同数据类型时发出,并建议使用 Categorical.from_codes)现在已被移除 (GH 8074)

  • MultiIndexlevelslabels 属性不能再直接设置 (GH 4039)。

  • pd.tseries.util.pivot_annual 已移除(自 v0.19 起弃用)。请改用 pivot_table (GH 18370)

  • pd.tseries.util.isleapyear 已移除(自 v0.19 起弃用)。请改用 Datetime 类似对象的 .is_leap_year 属性 (GH 18370)

  • pd.ordered_merge 已移除(自 v0.19 起弃用)。请改用 pd.merge_ordered (GH 18459)

  • SparseList 类已移除 (GH 14007)

  • pandas.io.wbpandas.io.data 存根模块已移除 (GH 13735)

  • Categorical.from_array 已移除 (GH 13854)

  • DataFrameSeriesrollingexpandingewm 方法已移除 freqhow 参数(自 v0.18 起弃用)。请改为在调用方法之前进行重采样 (GH 18601 & GH 18668)

  • DatetimeIndex.to_datetimeTimestamp.to_datetimePeriodIndex.to_datetimeIndex.to_datetime 已移除 (GH 8254, GH 14096, GH 14113)

  • read_csv() 已移除 skip_footer 参数 (GH 13386)

  • read_csv() 已移除 as_recarray 参数 (GH 13373)

  • read_csv() 已移除 buffer_lines 参数 (GH 13360)

  • read_csv() 已移除 compact_intsuse_unsigned 参数 (GH 13323)

  • Timestamp 类已移除 offset 属性,推荐使用 freq (GH 13593)

  • SeriesCategoricalIndex 类已移除 reshape 方法 (GH 13012)

  • pandas.tseries.frequencies.get_standard_freq 已移除,推荐使用 pandas.tseries.frequencies.to_offset(freq).rule_code (GH 13874)

  • pandas.tseries.frequencies.to_offset 已移除 freqstr 关键字,推荐使用 freq (GH 13874)

  • Panel4DPanelND 类已移除 (GH 13776)

  • Panel 类已移除 to_longtoLong 方法 (GH 19077)

  • 选项 display.line_withdisplay.height 已移除,分别推荐使用 display.widthdisplay.max_rows (GH 4391, GH 19107)

  • Categorical 类的 labels 属性已移除,推荐使用 Categorical.codes (GH 7768)

  • to_sql() 方法已移除 flavor 参数 (GH 13611)

  • 模块 pandas.tools.hashingpandas.util.hashing 已移除 (GH 16223)

  • 顶层函数 pd.rolling_*pd.expanding_*pd.ewm* 已移除(自 v0.18 起弃用)。请改用 DataFrame/Series 方法 rollingexpandingewm (GH 18723)

  • pandas.core.common 导入函数(如 is_datetime64_dtype)现已移除。这些函数位于 pandas.api.types 中。(GH 13634, GH 19769)

  • Series.tz_localize()DatetimeIndex.tz_localize()DatetimeIndex 中的 infer_dst 关键字已移除。infer_dst=True 等同于 ambiguous='infer'infer_dst=False 等同于 ambiguous='raise' (GH 7963)。

  • 当 `.resample()` 从 v0.18.0 中像 `.groupby()` 一样从即时操作更改为延迟操作时,我们引入了兼容性(带有 FutureWarning),以便操作能继续工作。现在此兼容性已完全移除,因此 Resampler 将不再转发兼容操作 (GH 20554)

  • 移除 .replace() 中长期弃用的 axis=None 参数 (GH 20271)

性能改进#

  • SeriesDataFrame 上的索引器不再创建引用循环 (GH 17956)

  • to_datetime() 添加了一个关键字参数 cache,它提高了转换重复日期时间参数的性能 (GH 11665)

  • DateOffset 算术运算性能得到改进 (GH 18218)

  • 通过对底层方法进行向量化,将 Timedelta 对象组成的 Series 转换为天、秒等操作的速度得到提升 (GH 18092)

  • 使用 Series/dict 输入提高了 .map() 的性能 (GH 15081)

  • 已移除 Timedelta 对象的 dayssecondsmicroseconds 重写属性,转而利用 Python 内置的版本 (GH 18242)

  • 在某些情况下,Series 构造将减少输入数据副本的数量 (GH 17449)

  • 提高了 Series.dt.date()DatetimeIndex.date() 的性能 (GH 18058)

  • 提高了 Series.dt.time()DatetimeIndex.time() 的性能 (GH 18461)

  • 提高了 IntervalIndex.symmetric_difference() 的性能 (GH 18475)

  • 改进了 DatetimeIndexSeries 算术运算在 Business-Month 和 Business-Quarter 频率下的性能 (GH 18489)

  • Series() / DataFrame() 的 tab 补全限制为 100 个值,以提高性能。 (GH 18587)

  • 改进了未安装 bottleneck 时,DataFrame.median()axis=1 参数下的性能 (GH 16468)

  • 改进了 MultiIndex.get_loc() 在大型索引上的性能,代价是小型索引性能略有下降 (GH 18519)

  • 改进了 MultiIndex.remove_unused_levels() 在没有未使用的层级时的性能,代价是在有未使用的层级时性能略有下降 (GH 19289)

  • 改进了 Index.get_loc() 在非唯一索引上的性能 (GH 19478)

  • 改进了成对 .rolling().expanding().cov().corr() 操作中的性能 (GH 17917)

  • 改进了 GroupBy.rank() 的性能 (GH 15779)

  • 改进了可变窗口 .rolling().min().max() 上的性能 (GH 19521)

  • 改进了 GroupBy.ffill()GroupBy.bfill() 的性能 (GH 11296)

  • 改进了 GroupBy.any()GroupBy.all() 的性能 (GH 15435)

  • 改进了 GroupBy.pct_change() 的性能 (GH 19165)

  • 改进了 Series.isin() 在 categorical dtypes 情况下的性能 (GH 20003)

  • 改进了当 Series 具有某些索引类型时,getattr(Series, attr) 的性能。这体现在大型 Series 使用 DatetimeIndex 时打印速度慢的问题上 (GH 19764)

  • 修复了 GroupBy.nth()GroupBy.last() 在包含某些对象列时出现的性能回退问题 (GH 19283)

  • 改进了 Categorical.from_codes() 的性能 (GH 18501)

文档更改#

感谢所有参与 3 月 10 日 pandas 文档冲刺的贡献者。我们有来自全球 30 多个地区的约 500 名参与者。您应该会注意到许多 API 文档字符串 已得到了极大的改进。

同时进行的贡献过多,无法为每项改进都包含一个发布说明,但这次 GitHub 搜索 应该能让您了解有多少文档字符串得到了改进。

特别感谢 Marc Garcia 组织了此次冲刺。欲了解更多信息,请阅读回顾冲刺的 NumFOCUS 博客文章

  • 将“numpy”的拼写更改为“NumPy”,将“python”更改为“Python”。 (GH 19017)

  • 引入代码示例时保持一致,使用冒号或句号。重写了一些句子以提高清晰度,增加了对函数、方法和类的更多动态引用。 (GH 18941, GH 18948, GH 18973, GH 19017)

  • 在合并文档的 concatenate 部分添加了对 DataFrame.assign() 的引用 (GH 18665)

错误修复#

分类数据#

警告

pandas 0.21 版本引入了一类与 CategoricalDtype 相关的错误,影响了诸如 mergeconcat 和索引等操作的正确性,尤其是在比较多个类别相同但顺序不同的无序 Categorical 数组时。我们强烈建议在执行这些操作之前升级或手动对齐您的类别。

  • Categorical.equals 中的错误,当比较两个类别相同但顺序不同的无序 Categorical 数组时返回错误结果 (GH 16603)

  • pandas.api.types.union_categoricals() 中的错误,当处理类别顺序不同的无序 categoricals 时返回错误结果。这影响了包含 Categorical data 的 pandas.concat() (GH 19096)。

  • pandas.merge() 中的错误,当在类别相同但顺序不同的无序 Categorical 上进行连接时返回错误结果 (GH 19551)

  • CategoricalIndex.get_indexer() 中的错误,当 target 是一个类别与 self 相同但顺序不同的无序 Categorical 时返回错误结果 (GH 19551)

  • Index.astype() 中的错误,在使用 categorical dtype 时,对于所有类型的索引,结果索引都未被转换为 CategoricalIndex (GH 18630)

  • Series.astype()Categorical.astype() 中的错误,现有 categorical data 未被更新 (GH 10696, GH 18593)

  • Series.str.split() 中的错误,在使用 expand=True 参数时,对于空字符串错误地引发了 IndexError (GH 20002)。

  • Index 构造函数中的错误,在使用 dtype=CategoricalDtype(...) 参数时,categoriesordered 未被保留 (GH 19032)

  • Series 构造函数中的错误,在使用标量和 dtype=CategoricalDtype(...) 参数时,categoriesordered 未被保留 (GH 19565)

  • Categorical.__iter__ 中的错误,未转换为 Python 类型 (GH 19909)

  • pandas.factorize() 中的错误,返回了 uniques 的唯一代码。现在此方法返回一个与输入具有相同 dtype 的 Categorical (GH 19721)

  • pandas.factorize() 中的错误,在 uniques 返回值中包含了缺失值的项 (GH 19721)

  • Series.take() 中的错误,在 categorical data 中将 indices 参数中的 -1 解释为缺失值标记,而不是 Series 的最后一个元素 (GH 20664)

日期/时间类#

  • Series.__sub__() 中的错误,将非纳秒级 np.datetime64 对象从 Series 中减去时得到错误结果 (GH 7996)

  • DatetimeIndex, TimedeltaIndex 中的错误,加减零维整数数组时得到错误结果 (GH 19012)

  • DatetimeIndexTimedeltaIndex 中的错误,在加减类似数组的 DateOffset 对象时,要么引发错误 (np.array, pd.Index),要么广播不正确 (pd.Series) (GH 18849)

  • Series.__add__() 中的错误,将 dtype 为 timedelta64[ns] 的 Series 添加到时区感知的 DatetimeIndex 时,错误地丢弃了时区信息 (GH 13905)

  • Period 对象添加到 datetimeTimestamp 对象时,现在将正确地引发 TypeError (GH 17983)

  • Timestamp 中的错误,与 Timestamp 对象数组进行比较时会导致 RecursionError (GH 15183)

  • Series floor-division 中的错误,对标量 timedelta 执行操作时会引发异常 (GH 18846)

  • DatetimeIndex 中的错误,其 repr 未显示一天结束时的高精度时间值(例如,23:59:59.999999999) (GH 19030)

  • .astype() 中的错误,转换为非纳秒级 timedelta 单位时会保持不正确的 dtype (GH 19176, GH 19223, GH 12425)

  • NaT 中减去 Series 时错误返回 NaT 的错误 (GH 19158)

  • Series.truncate() 中的错误,在使用单调 PeriodIndex 时会引发 TypeError (GH 17717)

  • pct_change() 中的错误,使用 periodsfreq 参数时返回了不同长度的输出 (GH 7292)

  • DatetimeIndexNonedatetime.date 对象比较中的错误,对于 ==!= 比较,本应分别返回全 False 和全 True,却引发了 TypeError (GH 19301)

  • Timestampto_datetime() 中的错误,表示微超出范围时间戳的字符串被错误地向下取整,而不是引发 OutOfBoundsDatetime (GH 19382)

  • Timestamp.floor() DatetimeIndex.floor() 中的错误,未来和过去很远的时间戳未被正确取整 (GH 19206)

  • to_datetime() 中的错误,在使用 errors='coerce'utc=True 参数时,传入超出范围的日期时间会引发 OutOfBoundsDatetime,而不是解析为 NaT (GH 19612)

  • DatetimeIndexTimedeltaIndex 加减法中的错误,返回对象的名称并非总是设置一致。 (GH 19744)

  • DatetimeIndexTimedeltaIndex 加减法中的错误,与 numpy 数组进行操作时引发了 TypeError (GH 19847)

  • DatetimeIndexTimedeltaIndex 中的错误,设置 freq 属性未能完全支持 (GH 20678)

时间差#

  • Timedelta.__mul__() 中的错误,与 NaT 相乘时返回了 NaT,而不是引发 TypeError (GH 19819)

  • dtype 为 dtype='timedelta64[ns]'Series 中的错误,与 TimedeltaIndex 相加或相减时结果被强制转换为 dtype='int64' (GH 17250)

  • dtype 为 dtype='timedelta64[ns]'Series 中的错误,与 TimedeltaIndex 相加或相减时可能返回名称不正确的 Series (GH 19043)

  • Timedelta.__floordiv__()Timedelta.__rfloordiv__() 中的错误,错误地允许与许多不兼容的 numpy 对象相除 (GH 18846)

  • 将标量 timedelta-like 对象与 TimedeltaIndex 相除时执行了倒数操作的错误 (GH 19125)

  • TimedeltaIndex 中的错误,与 Series 相除时返回了 TimedeltaIndex 而不是 Series (GH 19042)

  • Timedelta.__add__(), Timedelta.__sub__() 中的错误,与 np.timedelta64 对象相加或相减时返回了另一个 np.timedelta64,而不是 Timedelta (GH 19738)

  • Timedelta.__floordiv__(), Timedelta.__rfloordiv__() 中的错误,与 Tick 对象进行操作时会引发 TypeError,而不是返回 numeric value (GH 19738)

  • Period.asfreq() 中的错误,靠近 datetime(1, 1, 1) 的 period 可能被错误转换 (GH 19643, GH 19834)

  • Timedelta.total_seconds() 中的错误,导致精度问题,例如 Timedelta('30S').total_seconds()==30.000000000000004 (GH 19458)

  • Timedelta.__rmod__() 中的错误,与 numpy.timedelta64 进行操作时返回了 timedelta64 对象,而不是 Timedelta (GH 19820)

  • TimedeltaIndexTimedeltaIndex 相乘时,在 length mismatch 的情况下,现在将引发 TypeError 而不是 ValueError (GH 19333)

  • 修复了使用 np.timedelta64 对象对 TimedeltaIndex 进行索引时引发 TypeError 的 bug (GH 20393)

时区#

  • 修复了从包含 tz-naive 和 tz-aware 值的数组创建 Series 时,resulting Series 的 dtype 是 tz-aware 而不是 object 的 bug (GH 16406)

  • 修复了 timezone-aware DatetimeIndexNaT 比较时错误地引发 TypeError 的 bug (GH 19276)

  • 修复了 DatetimeIndex.astype() 在 timezone aware dtypes 之间转换以及从 timezone aware 转换为 naive 时存在的 bug (GH 18951)

  • 修复了 DatetimeIndex 比较时,当尝试比较 timezone-aware 和 timezone-naive datetime-like 对象时未能引发 TypeError 的 bug (GH 18162)

  • 修复了在 Series 构造函数中使用 datetime64[ns, tz] dtype 时,对 naive datetime 字符串进行本地化时存在的 bug (GH 174151)

  • Timestamp.replace() 现在将优雅地处理夏令时转换 (GH 18319)

  • 修复了 tz-aware DatetimeIndexTimedeltaIndexdtype='timedelta64[ns]' 数组进行加/减运算时结果不正确的 bug (GH 17558)

  • 修复了 DatetimeIndex.insert()NaT 插入 timezone-aware index 时错误地引发异常的 bug (GH 16357)

  • 修复了 DataFrame 构造函数中,tz-aware Datetimeindex 和给定的列名会导致一个空的 DataFrame 的 bug (GH 19157)

  • 修复了 Timestamp.tz_localize() 在本地化接近最小或最大有效值的 timestamp 时可能溢出并返回具有不正确纳秒值的 timestamp 的 bug (GH 12677)

  • 修复了迭代使用固定时区偏移进行本地化,并将纳秒精度四舍五入到微秒的 DatetimeIndex 时存在的 bug (GH 19603)

  • 修复了 DataFrame.diff() 在处理 tz-aware 值时引发 IndexError 的 bug (GH 18578)

  • 修复了 melt() 将 tz-aware dtypes 转换为 tz-naive 的 bug (GH 15785)

  • 修复了在对包含 timezone-aware 值的单列调用 Dataframe.dropna() 后,Dataframe.count() 引发 ValueError 的 bug (GH 13407)

偏移量#

  • 修复了 WeekOfMonthWeek 在加减运算时滚动不正确的 bug (GH 18510, GH 18672, GH 18864)

  • 修复了 WeekOfMonthLastWeekOfMonth 的构造函数中默认关键字参数引发 ValueError 的 bug (GH 19142)

  • 修复了 FY5253QuarterLastWeekOfMonth 的回滚和前滚行为与加减行为不一致的 bug (GH 18854)

  • 修复了 FY5253 在对年末但未归一化到午夜的日期进行 datetime 加减运算时增量不正确的 bug (GH 18854)

  • 修复了 FY5253 中 date offsets 在算术运算中可能错误地引发 AssertionError 的 bug (GH 14774)

数值#

  • 修复了 Series 构造函数在接收 int 或 float 列表并指定 dtype=strdtype='str'dtype='U' 时未能将数据元素转换为字符串的 bug (GH 16605)

  • 修复了 Index 的乘法和除法方法在与 Series 进行运算时返回 Index 对象而不是 Series 对象的 bug (GH 19042)

  • 修复了 DataFrame 构造函数中,包含非常大正数或负数的数据导致 OverflowError 的 bug (GH 18584)

  • 修复了 Index 构造函数在使用 dtype='uint64' 时,未将 int-like float 强制转换为 UInt64Index 的 bug (GH 18400)

  • 修复了 DataFrame 的 flex 算术运算 (例如 df.add(other, fill_value=foo)) 在 fill_value 不是 None 时,当 frame 或 other 的长度为零时未能引发 NotImplementedError 的 bug (GH 19522)

  • 修复了数值 dtype 的 Index 对象与 timedelta-like scalar 进行乘法和除法运算时返回 TimedeltaIndex 而不是引发 TypeError 的 bug (GH 19333)

  • 修复了当 fill_method 不是 None 时,Series.pct_change()DataFrame.pct_change() 返回 NaN 而不是 0 的 bug (GH 19873)

字符串#

索引#

  • 修复了从包含混合类型元组的列表构建 Index 时存在的 bug (GH 18505)

  • 修复了 Index.drop() 在传入同时包含元组和非元组的列表时存在的 bug (GH 18304)

  • 修复了 DataFrame.drop()Panel.drop()Series.drop()Index.drop() 在从包含重复项的轴删除不存在的元素时未引发 KeyError 的 bug (GH 19186)

  • 修复了索引 datetime-like Index 时引发 ValueError 而不是 IndexError 的 bug (GH 18386)

  • Index.to_series() 现在接受 indexname 关键字参数 (GH 18699)

  • DatetimeIndex.to_series() 现在接受 indexname 关键字参数 (GH 18699)

  • 修复了从具有非唯一 IndexSeries 索引非标量值时会返回扁平化值的 bug (GH 17610)

  • 修复了使用只包含缺失键的迭代器进行索引时未引发错误 (GH 20748)

  • 修复了当索引为整数 dtype 且不包含期望的键时,.ix 在使用列表和标量键之间存在的不一致性 (GH 20753)

  • 修复了使用 2 维布尔 ndarray 对 DataFrame 进行索引时,__setitem__ 中存在的 bug (GH 18582)

  • 修复了 str.extractall 在没有匹配项时返回空 Index 而不是适当的 MultiIndex 的 bug (GH 19034)

  • 修复了 IntervalIndex 在构建空数据或纯 NA 数据时,根据构建方法不同存在不一致性的 bug (GH 18421)

  • 修复了 IntervalIndex.symmetric_difference() 与非 IntervalIndex 进行对称差分时未引发异常的 bug (GH 18475)

  • 修复了 IntervalIndex 中返回空 IntervalIndex 的集合运算具有错误 dtype 的 bug (GH 19101)

  • 修复了 DataFrame.drop_duplicates() 在传入 DataFrame 中不存在的列时未引发 KeyError 的 bug (GH 19726)

  • 修复了 Index 子类的构造函数忽略意外关键字参数的 bug (GH 19348)

  • 修复了 Index.difference() 计算 Index 与自身差异时存在的 bug (GH 20040)

  • 修复了在值中间存在整行 NaNs 时,DataFrame.first_valid_index()DataFrame.last_valid_index() 中的 bug (GH 20499)

  • 修复了 IntervalIndex 在处理重叠或非单调的 uint64 数据时不支持某些索引操作的 bug (GH 20636)

  • 修复了 Series.is_unique 中,如果 Series 包含定义了 __ne__ 的对象,则在 stderr 中显示额外输出的 bug (GH 20661)

  • 修复了 .loc 使用单元素 list-like 进行赋值时错误地赋值为列表的 bug (GH 19474)

  • 修复了对具有单调递减 DatetimeIndexSeries/DataFrame 进行部分字符串索引时存在的 bug (GH 19362)

  • 修复了对具有重复 IndexDataFrame 执行原地操作时存在的 bug (GH 17105)

  • 修复了 IntervalIndex.get_loc()IntervalIndex.get_indexer() 在用于包含单个间隔的 IntervalIndex 时存在的 bug (GH 17284, GH 20921)

  • 修复了 .loc 使用 uint64 indexer 时存在的 bug (GH 20722)

多级索引#

IO#

绘图#

  • 尝试绘图但未安装 matplotlib 时提供更好的错误消息 (GH 19810)。

  • DataFrame.plot() 现在在 xy 参数格式不正确时引发 ValueError (GH 18671)

  • DataFrame.plot() 中,当 xy 参数以位置形式给出时,导致折线图、条形图和面积图引用列不正确的问题 (GH 20056)

  • 使用 datetime.time() 和小数秒格式化刻度标签时出现问题 (GH 18478)。

  • Series.plot.kde() 在文档字符串中暴露了参数 indbw_method (GH 18461)。参数 ind 现在也可以是整数(样本点数)。

  • DataFrame.plot() 现在支持 y 参数使用多个列 (GH 19699)

GroupBy/resample/rolling#

  • 按单个列分组并使用 listtuple 等类进行聚合时出现问题 (GH 18079)

  • 修复了 DataFrame.groupby() 中的回归问题,该问题在调用时使用不在索引中的元组键不会发出错误 (GH 18798)

  • DataFrame.resample() 中,静默忽略 labelclosedconvention 的不支持(或拼写错误)选项的问题 (GH 19303)

  • DataFrame.groupby() 中,元组被解释为键列表而不是键的问题 (GH 17979, GH 18249)

  • DataFrame.groupby() 中,通过 first/last/min/max 聚合导致时间戳丢失精度的问题 (GH 19526)

  • DataFrame.transform() 中,特定的聚合函数被错误地转换为与分组数据 dtype 匹配的问题 (GH 19200)

  • DataFrame.groupby() 中,传递 on= kwarg 然后使用 .apply() 时出现问题 (GH 17813)

  • DataFrame.resample().aggregate 中,聚合不存在的列时未能引发 KeyError 的问题 (GH 16766, GH 19566)

  • DataFrameGroupBy.cumsum()DataFrameGroupBy.cumprod() 中,传递 skipna 时出现问题 (GH 19806)

  • DataFrame.resample() 中,丢失时区信息的问题 (GH 13238)

  • DataFrame.groupby() 中,使用 np.allnp.any 进行转换时引发 ValueError 的问题 (GH 20653)

  • DataFrame.resample() 中,ffill, bfill, pad, backfill, fillna, interpolateasfreq 忽略 loffset 的问题。 (GH 20744)

  • DataFrame.groupby() 中,应用具有混合数据类型且用户提供的函数可能在分组列上失败的函数时出现问题 (GH 20949)

  • DataFrameGroupBy.rolling().apply() 中,对相关 DataFrameGroupBy 对象执行的操作可能会影响分组项是否包含在结果中的问题 (GH 14013)

稀疏数据#

  • 从密集 Series 或不支持的类型创建 SparseDataFrame 时引发未受控异常的问题 (GH 19374)

  • SparseDataFrame.to_csv 导致异常的问题 (GH 19384)

  • SparseSeries.memory_usage 通过访问非稀疏元素导致段错误的错误 (GH 19368)

  • 构造 SparseArray 时出现的问题:如果 data 是标量且定义了 index,则无论标量的 dtype 如何,都会强制转换为 float64。 (GH 19163)

重塑#

其他#

贡献者#

共有 328 人为此版本贡献了补丁。名字旁边带有“+”的人是第一次贡献补丁。

  • Aaron Critchley

  • AbdealiJK +

  • Adam Hooper +

  • Albert Villanova del Moral

  • Alejandro Giacometti +

  • Alejandro Hohmann +

  • Alex Rychyk

  • Alexander Buchkovsky

  • Alexander Lenail +

  • Alexander Michael Schade

  • Aly Sivji +

  • Andreas Költringer +

  • Andrew

  • Andrew Bui +

  • András Novoszáth +

  • Andy Craze +

  • Andy R. Terrel

  • Anh Le +

  • Anil Kumar Pallekonda +

  • Antoine Pitrou +

  • Antonio Linde +

  • Antonio Molina +

  • Antonio Quinonez +

  • Armin Varshokar +

  • Artem Bogachev +

  • Avi Sen +

  • Azeez Oluwafemi +

  • Ben Auffarth +

  • Bernhard Thiel +

  • Bhavesh Poddar +

  • BielStela +

  • Blair +

  • Bob Haffner

  • Brett Naul +

  • Brock Mendel

  • Bryce Guinta +

  • Carlos Eduardo Moreira dos Santos +

  • Carlos García Márquez +

  • Carol Willing

  • Cheuk Ting Ho +

  • Chitrank Dixit +

  • Chris

  • Chris Burr +

  • Chris Catalfo +

  • Chris Mazzullo

  • Christian Chwala +

  • Cihan Ceyhan +

  • Clemens Brunner

  • Colin +

  • Cornelius Riemenschneider

  • Crystal Gong +

  • DaanVanHauwermeiren

  • Dan Dixey +

  • Daniel Frank +

  • Daniel Garrido +

  • Daniel Sakuma +

  • DataOmbudsman +

  • Dave Hirschfeld

  • Dave Lewis +

  • David Adrián Cañones Castellano +

  • David Arcos +

  • David C Hall +

  • David Fischer

  • David Hoese +

  • David Lutz +

  • David Polo +

  • David Stansby

  • Dennis Kamau +

  • Dillon Niederhut

  • Dimitri +

  • Dr. Irv

  • Dror Atariah

  • Eric Chea +

  • Eric Kisslinger

  • Eric O. LEBIGOT (EOL) +

  • FAN-GOD +

  • Fabian Retkowski +

  • Fer Sar +

  • Gabriel de Maeztu +

  • Gianpaolo Macario +

  • Giftlin Rajaiah

  • Gilberto Olimpio +

  • Gina +

  • Gjelt +

  • Graham Inggs +

  • Grant Roch

  • Grant Smith +

  • Grzegorz Konefał +

  • Guilherme Beltramini

  • HagaiHargil +

  • Hamish Pitkeathly +

  • Hammad Mashkoor +

  • Hannah Ferchland +

  • Hans

  • Haochen Wu +

  • Hissashi Rocha +

  • Iain Barr +

  • Ibrahim Sharaf ElDen +

  • Ignasi Fosch +

  • Igor Conrado Alves de Lima +

  • Igor Shelvinskyi +

  • Imanflow +

  • Ingolf Becker

  • Israel Saeta Pérez

  • Iva Koevska +

  • Jakub Nowacki +

  • Jan F-F +

  • Jan Koch +

  • Jan Werkmann

  • Janelle Zoutkamp +

  • Jason Bandlow +

  • Jaume Bonet +

  • Jay Alammar +

  • Jeff Reback

  • JennaVergeynst

  • Jimmy Woo +

  • Jing Qiang Goh +

  • Joachim Wagner +

  • Joan Martin Miralles +

  • Joel Nothman

  • Joeun Park +

  • John Cant +

  • Johnny Metz +

  • Jon Mease

  • Jonas Schulze +

  • Jongwony +

  • Jordi Contestí +

  • Joris Van den Bossche

  • José F. R. Fonseca +

  • Jovixe +

  • Julio Martinez +

  • Jörg Döpfert

  • KOBAYASHI Ittoku +

  • Kate Surta +

  • Kenneth +

  • Kevin Kuhl

  • Kevin Sheppard

  • Krzysztof Chomski

  • Ksenia +

  • Ksenia Bobrova +

  • Kunal Gosar +

  • Kurtis Kerstein +

  • Kyle Barron +

  • Laksh Arora +

  • Laurens Geffert +

  • Leif Walsh

  • Liam Marshall +

  • Liam3851 +

  • Licht Takeuchi

  • Liudmila +

  • Ludovico Russo +

  • Mabel Villalba +

  • Manan Pal Singh +

  • Manraj Singh

  • Marc +

  • Marc Garcia

  • Marco Hemken +

  • Maria del Mar Bibiloni +

  • Mario Corchero +

  • Mark Woodbridge +

  • Martin Journois +

  • Mason Gallo +

  • Matias Heikkilä +

  • Matt Braymer-Hayes

  • Matt Kirk +

  • Matt Maybeno +

  • Matthew Kirk +

  • Matthew Rocklin +

  • Matthew Roeschke

  • Matthias Bussonnier +

  • Max Mikhaylov +

  • Maxim Veksler +

  • Maximilian Roos

  • Maximiliano Greco +

  • Michael Penkov

  • Michael Röttger +

  • Michael Selik +

  • Michael Waskom

  • Mie~~~

  • Mike Kutzma +

  • Ming Li +

  • Mitar +

  • Mitch Negus +

  • Montana Low +

  • Moritz Münst +

  • Mortada Mehyar

  • Myles Braithwaite +

  • Nate Yoder

  • Nicholas Ursa +

  • Nick Chmura

  • Nikos Karagiannakis +

  • Nipun Sadvilkar +

  • Nis Martensen +

  • Noah +

  • Noémi Éltető +

  • Olivier Bilodeau +

  • Ondrej Kokes +

  • Onno Eberhard +

  • Paul Ganssle +

  • Paul Mannino +

  • Paul Reidy

  • Paulo Roberto de Oliveira Castro +

  • Pepe Flores +

  • Peter Hoffmann

  • Phil Ngo +

  • Pietro Battiston

  • Pranav Suri +

  • Priyanka Ojha +

  • Pulkit Maloo +

  • README Bot +

  • Ray Bell +

  • Riccardo Magliocchetti +

  • Ridhwan Luthra +

  • Robert Meyer

  • Robin

  • Robin Kiplang’at +

  • Rohan Pandit +

  • Rok Mihevc +

  • Rouz Azari

  • Ryszard T. Kaleta +

  • Sam Cohan

  • Sam Foo

  • Samir Musali +

  • Samuel Sinayoko +

  • Sangwoong Yoon

  • SarahJessica +

  • Sharad Vijalapuram +

  • Shubham Chaudhary +

  • SiYoungOh +

  • Sietse Brouwer

  • Simone Basso +

  • Stefania Delprete +

  • Stefano Cianciulli +

  • Stephen Childs +

  • StephenVoland +

  • Stijn Van Hoey +

  • Sven

  • Talitha Pumar +

  • Tarbo Fukazawa +

  • Ted Petrou +

  • Thomas A Caswell

  • Tim Hoffmann +

  • Tim Swast

  • Tom Augspurger

  • Tommy +

  • Tulio Casagrande +

  • Tushar Gupta +

  • Tushar Mittal +

  • Upkar Lidder +

  • Victor Villas +

  • Vince W +

  • Vinícius Figueiredo +

  • Vipin Kumar +

  • WBare

  • Wenhuan +

  • Wes Turner

  • William Ayd

  • Wilson Lin +

  • Xbar

  • Yaroslav Halchenko

  • Yee Mey

  • Yeongseon Choe +

  • Yian +

  • Yimeng Zhang

  • ZhuBaohe +

  • Zihao Zhao +

  • adatasetaday +

  • akielbowicz +

  • akosel +

  • alinde1 +

  • amuta +

  • bolkedebruin

  • cbertinato

  • cgohlke

  • charlie0389 +

  • chris-b1

  • csfarkas +

  • dajcs +

  • deflatSOCO +

  • derestle-htwg

  • discort

  • dmanikowski-reef +

  • donK23 +

  • elrubio +

  • fivemok +

  • fjdiod

  • fjetter +

  • froessler +

  • gabrielclow

  • gfyoung

  • ghasemnaddaf

  • h-vetinari +

  • himanshu awasthi +

  • ignamv +

  • jayfoad +

  • jazzmuesli +

  • jbrockmendel

  • jen w +

  • jjames34 +

  • joaoavf +

  • joders +

  • jschendel

  • juan huguet +

  • l736x +

  • luzpaz +

  • mdeboc +

  • miguelmorin +

  • miker985

  • miquelcamprodon +

  • orereta +

  • ottiP +

  • peterpanmj +

  • rafarui +

  • raph-m +

  • readyready15728 +

  • rmihael +

  • samghelms +

  • scriptomation +

  • sfoo +

  • stefansimik +

  • stonebig

  • tmnhat2001 +

  • tomneep +

  • topper-123

  • tv3141 +

  • verakai +

  • xpvpc +

  • zhanghui +