0.24.0 中的新增功能 (2019 年 1 月 25 日)#

警告

0.24.x 系列版本将是最后一个支持 Python 2 的版本。未来的功能版本将仅支持 Python 3。有关更多详细信息,请参阅放弃 Python 2.7

这是自 0.23.4 以来的一个主要版本,包含多项 API 变更、新功能、增强功能和性能改进,以及大量的错误修复。

亮点包括

更新前请查看API 变更弃用内容

以上是 pandas 0.24.0 中的变化。有关包含其他 pandas 版本在内的完整变更日志,请参阅版本说明

增强功能#

可选整数 NA 支持#

pandas 获得了支持包含缺失值的整数数据类型的能力。这项期待已久的功能通过使用扩展类型实现。

注意

IntegerArray 目前处于实验阶段。其 API 或实现方式可能在未通知的情况下发生变化。

我们可以构造一个指定 dtype 的 Series。dtype 字符串 Int64 是一个 pandas ExtensionDtype。使用传统的缺失值标记 np.nan 指定列表或数组时,将推断为整数 dtype。Series 的显示也会在字符串输出中使用 NaN 来指示缺失值。(GH 20700, GH 20747, GH 22441, GH 21789, GH 22346)

In [1]: s = pd.Series([1, 2, np.nan], dtype='Int64')

In [2]: s
Out[2]: 
0       1
1       2
2    <NA>
Length: 3, dtype: Int64

对这些 dtype 的操作将像其他 pandas 操作一样传播 NaN

# arithmetic
In [3]: s + 1
Out[3]: 
0       2
1       3
2    <NA>
Length: 3, dtype: Int64

# comparison
In [4]: s == 1
Out[4]: 
0     True
1    False
2     <NA>
Length: 3, dtype: boolean

# indexing
In [5]: s.iloc[1:3]
Out[5]: 
1       2
2    <NA>
Length: 2, dtype: Int64

# operate with other dtypes
In [6]: s + s.iloc[1:3].astype('Int8')
Out[6]: 
0    <NA>
1       4
2    <NA>
Length: 3, dtype: Int64

# coerce when needed
In [7]: s + 0.01
Out[7]: 
0    1.01
1    2.01
2    <NA>
Length: 3, dtype: Float64

这些 dtype 可以作为 DataFrame 的一部分进行操作。

In [8]: df = pd.DataFrame({'A': s, 'B': [1, 1, 3], 'C': list('aab')})

In [9]: df
Out[9]: 
      A  B  C
0     1  1  a
1     2  1  a
2  <NA>  3  b

[3 rows x 3 columns]

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

这些 dtype 可以合并、重塑和转换类型。

In [11]: pd.concat([df[['A']], df[['B', 'C']]], axis=1).dtypes
Out[11]: 
A     Int64
B     int64
C    object
Length: 3, dtype: object

In [12]: df['A'].astype(float)
Out[12]: 
0    1.0
1    2.0
2    NaN
Name: A, Length: 3, dtype: float64

求约简和 groupby 操作(如 sum)有效。

In [13]: df.sum()
Out[13]: 
A      3
B      5
C    aab
Length: 3, dtype: object

In [14]: df.groupby('B').A.sum()
Out[14]: 
B
1    3
3    0
Name: A, Length: 2, dtype: Int64

警告

当前的整数 NA 支持使用大写 dtype 版本,例如 Int8,而不是传统的 int8。这将来可能会改变。

更多信息请参阅可空整数数据类型

访问 Series 或 Index 中的值#

Series.arrayIndex.array 已添加,用于提取 SeriesIndex 的底层数组。(GH 19954, GH 23623)

In [15]: idx = pd.period_range('2000', periods=4)

In [16]: idx.array
Out[16]: 
<PeriodArray>
['2000-01-01', '2000-01-02', '2000-01-03', '2000-01-04']
Length: 4, dtype: period[D]

In [17]: pd.Series(idx).array
Out[17]: 
<PeriodArray>
['2000-01-01', '2000-01-02', '2000-01-03', '2000-01-04']
Length: 4, dtype: period[D]

历史上,这会通过 series.values 完成,但对于 .values,不清楚返回的值是实际数组、它的某种转换,还是 pandas 的自定义数组之一(例如 Categorical)。例如,对于 PeriodIndex.values 每次都会生成一个新的由 period 对象组成的 ndarray。

In [18]: idx.values
Out[18]: 
array([Period('2000-01-01', 'D'), Period('2000-01-02', 'D'),
       Period('2000-01-03', 'D'), Period('2000-01-04', 'D')], dtype=object)

In [19]: id(idx.values)
Out[19]: 140636498013488

In [20]: id(idx.values)
Out[20]: 140636537481968

如果需要实际的 NumPy 数组,请使用 Series.to_numpy()Index.to_numpy()

In [21]: idx.to_numpy()
Out[21]: 
array([Period('2000-01-01', 'D'), Period('2000-01-02', 'D'),
       Period('2000-01-03', 'D'), Period('2000-01-04', 'D')], dtype=object)

In [22]: pd.Series(idx).to_numpy()
Out[22]: 
array([Period('2000-01-01', 'D'), Period('2000-01-02', 'D'),
       Period('2000-01-03', 'D'), Period('2000-01-04', 'D')], dtype=object)

对于由普通 NumPy 数组支持的 Series 和 Index,Series.array 将返回一个新的 arrays.PandasArray,它是一个围绕 numpy.ndarray 的轻量级(无复制)包装器。PandasArray 本身不是特别有用,但它提供了与 pandas 或第三方库中定义的任何扩展数组相同的接口。

In [23]: ser = pd.Series([1, 2, 3])

In [24]: ser.array
Out[24]: 
<NumpyExtensionArray>
[1, 2, 3]
Length: 3, dtype: int64

In [25]: ser.to_numpy()
Out[25]: array([1, 2, 3])

我们尚未移除或弃用 Series.valuesDataFrame.values,但强烈建议改用 .array.to_numpy()

更多信息请参阅数据类型属性和底层数据

pandas.array:创建数组的新顶层方法#

已添加新的顶层方法 array() 用于创建一维数组 (GH 22860)。此方法可用于创建任何扩展数组,包括由第三方库注册的扩展数组。有关扩展数组的更多信息,请参阅dtypes 文档

In [26]: pd.array([1, 2, np.nan], dtype='Int64')
Out[26]: 
<IntegerArray>
[1, 2, <NA>]
Length: 3, dtype: Int64

In [27]: pd.array(['a', 'b', 'c'], dtype='category')
Out[27]: 
['a', 'b', 'c']
Categories (3, object): ['a', 'b', 'c']

传递没有专门扩展类型的数据(例如 float, integer 等)将返回一个新的 arrays.PandasArray,它只是一个围绕 numpy.ndarray 的轻量级(无复制)包装器,并满足 pandas 扩展数组接口。

In [28]: pd.array([1, 2, 3])
Out[28]: 
<IntegerArray>
[1, 2, 3]
Length: 3, dtype: Int64

PandasArray 本身并不是一个非常有用的对象。但是如果你需要编写能够通用地处理任何 ExtensionArray 的底层代码,PandasArray 可以满足这个需求。

注意,默认情况下,如果未指定 dtype,返回数组的 dtype 将从数据中推断。特别注意,第一个示例 [1, 2, np.nan] 会返回一个浮点数组,因为 NaN 是一个浮点数。

In [29]: pd.array([1, 2, np.nan])
Out[29]: 
<IntegerArray>
[1, 2, <NA>]
Length: 3, dtype: Int64

在 Series 和 DataFrame 中存储 Interval 和 Period 数据#

IntervalPeriod 数据现在可以存储在 SeriesDataFrame 中,而不仅限于像以前那样存储在 IntervalIndexPeriodIndex 中 (GH 19453, GH 22862)。

In [30]: ser = pd.Series(pd.interval_range(0, 5))

In [31]: ser
Out[31]: 
0    (0, 1]
1    (1, 2]
2    (2, 3]
3    (3, 4]
4    (4, 5]
Length: 5, dtype: interval

In [32]: ser.dtype
Out[32]: interval[int64, right]

对于 periods

In [33]: pser = pd.Series(pd.period_range("2000", freq="D", periods=5))

In [34]: pser
Out[34]: 
0    2000-01-01
1    2000-01-02
2    2000-01-03
3    2000-01-04
4    2000-01-05
Length: 5, dtype: period[D]

In [35]: pser.dtype
Out[35]: period[D]

以前,这些会被转换为 object dtype 的 NumPy 数组。一般来说,这在 SeriesDataFrame 的列中存储 intervals 或 periods 数组时,应会带来更好的性能。

使用 Series.arraySeries 中提取底层 intervals 或 periods 数组

In [36]: ser.array
Out[36]: 
<IntervalArray>
[(0, 1], (1, 2], (2, 3], (3, 4], (4, 5]]
Length: 5, dtype: interval[int64, right]

In [37]: pser.array
Out[37]: 
<PeriodArray>
['2000-01-01', '2000-01-02', '2000-01-03', '2000-01-04', '2000-01-05']
Length: 5, dtype: period[D]

这些返回 arrays.IntervalArrayarrays.PeriodArray 的实例,它们是支持 interval 和 period 数据的新扩展数组。

警告

为了向后兼容,对于 Interval 和 Period 数据,Series.values 继续返回一个由 object 组成的 NumPy 数组。建议在需要存储在 Series 中的数据数组时使用 Series.array,并在确定需要 NumPy 数组时使用 Series.to_numpy()

更多信息请参阅数据类型属性和底层数据

基于两个 MultiIndex 进行合并#

DataFrame.merge()DataFrame.join() 现在可用于在重叠的索引级别上合并 MultiIndex 的 DataFrame 实例 (GH 6360)

请参阅合并、连接和连接(Merge, join, and concatenate)文档部分。

In [38]: index_left = pd.MultiIndex.from_tuples([('K0', 'X0'), ('K0', 'X1'),
   ....:                                        ('K1', 'X2')],
   ....:                                        names=['key', 'X'])
   ....: 

In [39]: left = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
   ....:                      'B': ['B0', 'B1', 'B2']}, index=index_left)
   ....: 

In [40]: index_right = pd.MultiIndex.from_tuples([('K0', 'Y0'), ('K1', 'Y1'),
   ....:                                         ('K2', 'Y2'), ('K2', 'Y3')],
   ....:                                         names=['key', 'Y'])
   ....: 

In [41]: right = pd.DataFrame({'C': ['C0', 'C1', 'C2', 'C3'],
   ....:                       'D': ['D0', 'D1', 'D2', 'D3']}, index=index_right)
   ....: 

In [42]: left.join(right)
Out[42]: 
            A   B   C   D
key X  Y                 
K0  X0 Y0  A0  B0  C0  D0
    X1 Y0  A1  B1  C0  D0
K1  X2 Y1  A2  B2  C1  D1

[3 rows x 4 columns]

对于更早的版本,可以使用以下方法完成。

In [43]: pd.merge(left.reset_index(), right.reset_index(),
   ....:          on=['key'], how='inner').set_index(['key', 'X', 'Y'])
   ....: 
Out[43]: 
            A   B   C   D
key X  Y                 
K0  X0 Y0  A0  B0  C0  D0
    X1 Y0  A1  B1  C0  D0
K1  X2 Y1  A2  B2  C1  D1

[3 rows x 4 columns]

函数 read_html 增强功能#

read_html() 以前会忽略 colspanrowspan 属性。现在它能够理解这些属性,并将它们视为具有相同值的连续单元格。(GH 17054)

In [44]: from io import StringIO

In [45]: result = pd.read_html(StringIO("""
   ....:   <table>
   ....:     <thead>
   ....:       <tr>
   ....:         <th>A</th><th>B</th><th>C</th>
   ....:       </tr>
   ....:     </thead>
   ....:     <tbody>
   ....:       <tr>
   ....:         <td colspan="2">1</td><td>2</td>
   ....:       </tr>
   ....:     </tbody>
   ....:   </table>"""))
   ....: 

旧行为:

In [13]: result
Out [13]:
[   A  B   C
 0  1  2 NaN]

新行为:

In [46]: result
Out[46]: 
[   A  B  C
 0  1  1  2
 
 [1 rows x 3 columns]]

新增 Styler.pipe() 方法#

Styler 类新增了 pipe() 方法。这提供了一种方便的方式来应用用户预定义的样式函数,并且有助于减少在 notebook 中重复使用 DataFrame 样式功能时的“样板代码”。(GH 23229)

In [47]: df = pd.DataFrame({'N': [1250, 1500, 1750], 'X': [0.25, 0.35, 0.50]})

In [48]: def format_and_align(styler):
   ....:     return (styler.format({'N': '{:,}', 'X': '{:.1%}'})
   ....:                   .set_properties(**{'text-align': 'right'}))
   ....: 

In [49]: df.style.pipe(format_and_align).set_caption('Summary of results.')
Out[49]: <pandas.io.formats.style.Styler at 0x7fe85f503d60>

pandas 的其他类中已存在类似方法,包括 DataFrame.pipe()GroupBy.pipe()Resampler.pipe()

重命名 MultiIndex 中的名称#

DataFrame.rename_axis() 现在支持 indexcolumns 参数,而 Series.rename_axis() 支持 index 参数 (GH 19978)。

此更改允许传递字典,以便更改 MultiIndex 中的某些名称。

示例

In [50]: mi = pd.MultiIndex.from_product([list('AB'), list('CD'), list('EF')],
   ....:                                 names=['AB', 'CD', 'EF'])
   ....: 

In [51]: df = pd.DataFrame(list(range(len(mi))), index=mi, columns=['N'])

In [52]: df
Out[52]: 
          N
AB CD EF   
A  C  E   0
      F   1
   D  E   2
      F   3
B  C  E   4
      F   5
   D  E   6
      F   7

[8 rows x 1 columns]

In [53]: df.rename_axis(index={'CD': 'New'})
Out[53]: 
           N
AB New EF   
A  C   E   0
       F   1
   D   E   2
       F   3
B  C   E   4
       F   5
   D   E   6
       F   7

[8 rows x 1 columns]

有关更多详细信息,请参阅有关重命名的进阶文档

其他增强功能#

向后不兼容的 API 变更#

pandas 0.24.0 包含一些 API 破坏性更改。

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

我们更新了依赖项的最低支持版本(GH 21242, GH 18742, GH 23774, GH 24767)。如果已安装,我们现在要求:

最低版本

必需

numpy

1.12.0

X

bottleneck

1.2.0

fastparquet

0.2.1

matplotlib

2.0.0

numexpr

2.6.1

pandas-gbq

0.8.0

pyarrow

0.9.0

pytables

3.4.2

scipy

0.18.1

xlrd

1.0.0

pytest (dev)

3.6

此外,我们不再依赖 feather-format 进行基于 feather 的存储,而是将其替换为引用 pyarrowGH 21639GH 23053)。

DataFrame.to_csv 的 line_terminator 使用 os.linesep#

DataFrame.to_csv() 现在使用 os.linesep() 作为默认行结束符,而不是 '\n'GH 20353)。此更改仅影响在 Windows 上运行,在 Windows 上即使在 line_terminator 中传递 '\n',也使用 '\r\n' 作为行结束符。

Windows 上的之前行为

In [1]: data = pd.DataFrame({"string_with_lf": ["a\nbc"],
   ...:                      "string_with_crlf": ["a\r\nbc"]})

In [2]: # When passing file PATH to to_csv,
   ...: # line_terminator does not work, and csv is saved with '\r\n'.
   ...: # Also, this converts all '\n's in the data to '\r\n'.
   ...: data.to_csv("test.csv", index=False, line_terminator='\n')

In [3]: with open("test.csv", mode='rb') as f:
   ...:     print(f.read())
Out[3]: b'string_with_lf,string_with_crlf\r\n"a\r\nbc","a\r\r\nbc"\r\n'

In [4]: # When passing file OBJECT with newline option to
   ...: # to_csv, line_terminator works.
   ...: with open("test2.csv", mode='w', newline='\n') as f:
   ...:     data.to_csv(f, index=False, line_terminator='\n')

In [5]: with open("test2.csv", mode='rb') as f:
   ...:     print(f.read())
Out[5]: b'string_with_lf,string_with_crlf\n"a\nbc","a\r\nbc"\n'

Windows 上的新行为

显式传递 line_terminator,将行结束符设置为该字符。

In [1]: data = pd.DataFrame({"string_with_lf": ["a\nbc"],
   ...:                      "string_with_crlf": ["a\r\nbc"]})

In [2]: data.to_csv("test.csv", index=False, line_terminator='\n')

In [3]: with open("test.csv", mode='rb') as f:
   ...:     print(f.read())
Out[3]: b'string_with_lf,string_with_crlf\n"a\nbc","a\r\nbc"\n'

在 Windows 上,os.linesep 的值是 '\r\n',因此如果未设置 line_terminator,则使用 '\r\n' 作为行结束符。

In [1]: data = pd.DataFrame({"string_with_lf": ["a\nbc"],
   ...:                      "string_with_crlf": ["a\r\nbc"]})

In [2]: data.to_csv("test.csv", index=False)

In [3]: with open("test.csv", mode='rb') as f:
   ...:     print(f.read())
Out[3]: b'string_with_lf,string_with_crlf\r\n"a\nbc","a\r\nbc"\r\n'

对于文件对象,指定 newline 不足以设置行结束符。即使在这种情况下,也必须显式传入 line_terminator

In [1]: data = pd.DataFrame({"string_with_lf": ["a\nbc"],
   ...:                      "string_with_crlf": ["a\r\nbc"]})

In [2]: with open("test2.csv", mode='w', newline='\n') as f:
   ...:     data.to_csv(f, index=False)

In [3]: with open("test2.csv", mode='rb') as f:
   ...:     print(f.read())
Out[3]: b'string_with_lf,string_with_crlf\r\n"a\nbc","a\r\nbc"\r\n'

使用 Python 引擎正确处理字符串数据类型列中的 np.nan#

在使用 Python 引擎的 read_excel()read_csv() 中存在一个错误,当 dtype=strna_filter=True 时,缺失值会变成 'nan'。现在,这些缺失值被转换为字符串缺失指示符 np.nan。(GH 20377

旧行为:

In [5]: data = 'a,b,c\n1,,3\n4,5,6'
In [6]: df = pd.read_csv(StringIO(data), engine='python', dtype=str, na_filter=True)
In [7]: df.loc[0, 'b']
Out[7]:
'nan'

新行为:

In [54]: data = 'a,b,c\n1,,3\n4,5,6'

In [55]: df = pd.read_csv(StringIO(data), engine='python', dtype=str, na_filter=True)

In [56]: df.loc[0, 'b']
Out[56]: nan

请注意,现在我们直接输出 np.nan 本身,而不是其字符串形式。

解析带有时区偏移的日期时间字符串#

以前,使用 to_datetime()DatetimeIndex 解析带 UTC 偏移的日期时间字符串时,会自动将日期时间转换为 UTC,而不带时区本地化。这与使用 Timestamp 解析相同日期时间字符串不一致,后者会在 tz 属性中保留 UTC 偏移。现在,当所有日期时间字符串具有相同的 UTC 偏移量时,to_datetime() 会在 tz 属性中保留 UTC 偏移量(GH 17697, GH 11736, GH 22457

旧行为:

In [2]: pd.to_datetime("2015-11-18 15:30:00+05:30")
Out[2]: Timestamp('2015-11-18 10:00:00')

In [3]: pd.Timestamp("2015-11-18 15:30:00+05:30")
Out[3]: Timestamp('2015-11-18 15:30:00+0530', tz='pytz.FixedOffset(330)')

# Different UTC offsets would automatically convert the datetimes to UTC (without a UTC timezone)
In [4]: pd.to_datetime(["2015-11-18 15:30:00+05:30", "2015-11-18 16:30:00+06:30"])
Out[4]: DatetimeIndex(['2015-11-18 10:00:00', '2015-11-18 10:00:00'], dtype='datetime64[ns]', freq=None)

新行为:

In [57]: pd.to_datetime("2015-11-18 15:30:00+05:30")
Out[57]: Timestamp('2015-11-18 15:30:00+0530', tz='UTC+05:30')

In [58]: pd.Timestamp("2015-11-18 15:30:00+05:30")
Out[58]: Timestamp('2015-11-18 15:30:00+0530', tz='UTC+05:30')

解析具有相同 UTC 偏移量的日期时间字符串将在 tz 中保留 UTC 偏移量

In [59]: pd.to_datetime(["2015-11-18 15:30:00+05:30"] * 2)
Out[59]: DatetimeIndex(['2015-11-18 15:30:00+05:30', '2015-11-18 15:30:00+05:30'], dtype='datetime64[ns, UTC+05:30]', freq=None)

解析具有不同 UTC 偏移量的日期时间字符串现在将创建一个包含不同 UTC 偏移量的 datetime.datetime 对象的 Index

In [59]: idx = pd.to_datetime(["2015-11-18 15:30:00+05:30",
                               "2015-11-18 16:30:00+06:30"])

In[60]: idx
Out[60]: Index([2015-11-18 15:30:00+05:30, 2015-11-18 16:30:00+06:30], dtype='object')

In[61]: idx[0]
Out[61]: Timestamp('2015-11-18 15:30:00+0530', tz='UTC+05:30')

In[62]: idx[1]
Out[62]: Timestamp('2015-11-18 16:30:00+0630', tz='UTC+06:30')

传递 utc=True 将模拟之前的行为,但会正确指示日期已转换为 UTC

In [60]: pd.to_datetime(["2015-11-18 15:30:00+05:30",
   ....:                 "2015-11-18 16:30:00+06:30"], utc=True)
   ....: 
Out[60]: DatetimeIndex(['2015-11-18 10:00:00+00:00', '2015-11-18 10:00:00+00:00'], dtype='datetime64[ns, UTC]', freq=None)

使用 read_csv 解析混合时区#

read_csv() 不再静默地将混合时区列转换为 UTC(GH 24987)。

旧行为

>>> import io
>>> content = """\
... a
... 2000-01-01T00:00:00+05:00
... 2000-01-01T00:00:00+06:00"""
>>> df = pd.read_csv(io.StringIO(content), parse_dates=['a'])
>>> df.a
0   1999-12-31 19:00:00
1   1999-12-31 18:00:00
Name: a, dtype: datetime64[ns]

新行为

In[64]: import io

In[65]: content = """\
   ...: a
   ...: 2000-01-01T00:00:00+05:00
   ...: 2000-01-01T00:00:00+06:00"""

In[66]: df = pd.read_csv(io.StringIO(content), parse_dates=['a'])

In[67]: df.a
Out[67]:
0   2000-01-01 00:00:00+05:00
1   2000-01-01 00:00:00+06:00
Name: a, Length: 2, dtype: object

可以看出,dtype 是 object;列中的每个值都是字符串。要将字符串转换为日期时间数组,可以使用 date_parser 参数。

In [3]: df = pd.read_csv(
   ...:     io.StringIO(content),
   ...:     parse_dates=['a'],
   ...:     date_parser=lambda col: pd.to_datetime(col, utc=True),
   ...: )

In [4]: df.a
Out[4]:
0   1999-12-31 19:00:00+00:00
1   1999-12-31 18:00:00+00:00
Name: a, dtype: datetime64[ns, UTC]

更多信息请参见 解析带有时区偏移的日期时间字符串

dt.end_time 和 to_timestamp(how='end') 中的时间值#

调用 Series.dt.end_time, Period.end_time, PeriodIndex.end_time, Period.to_timestamp() 带有 how='end',或 PeriodIndex.to_timestamp() 带有 how='end' 时,PeriodPeriodIndex 对象中的时间值现在设置为 ‘23:59:59.999999999’(GH 17157

旧行为:

In [2]: p = pd.Period('2017-01-01', 'D')
In [3]: pi = pd.PeriodIndex([p])

In [4]: pd.Series(pi).dt.end_time[0]
Out[4]: Timestamp(2017-01-01 00:00:00)

In [5]: p.end_time
Out[5]: Timestamp(2017-01-01 23:59:59.999999999)

新行为:

例如,调用 Series.dt.end_time 现在将导致时间为 ‘23:59:59.999999999’,与 Period.end_time 的情况相同

In [61]: p = pd.Period('2017-01-01', 'D')

In [62]: pi = pd.PeriodIndex([p])

In [63]: pd.Series(pi).dt.end_time[0]
Out[63]: Timestamp('2017-01-01 23:59:59.999999999')

In [64]: p.end_time
Out[64]: Timestamp('2017-01-01 23:59:59.999999999')

用于时区感知数据的 Series.unique#

对于带有时区值的日期时间,Series.unique() 的返回类型已从 Timestamp 对象的 numpy.ndarray 更改为 arrays.DatetimeArrayGH 24024)。

In [65]: ser = pd.Series([pd.Timestamp('2000', tz='UTC'),
   ....:                  pd.Timestamp('2000', tz='UTC')])
   ....: 

旧行为:

In [3]: ser.unique()
Out[3]: array([Timestamp('2000-01-01 00:00:00+0000', tz='UTC')], dtype=object)

新行为:

In [66]: ser.unique()
Out[66]: 
<DatetimeArray>
['2000-01-01 00:00:00+00:00']
Length: 1, dtype: datetime64[ns, UTC]

稀疏数据结构重构#

SparseArray 是支持 SparseSeriesSparseDataFrame 中列的数组,现在是扩展数组(GH 21978, GH 19056, GH 22835)。为了符合此接口并与 pandas 的其余部分保持一致,进行了一些 API 破坏性更改:

  • SparseArray 不再是 numpy.ndarray 的子类。要将 SparseArray 转换为 NumPy 数组,请使用 numpy.asarray()

  • SparseArray.dtypeSparseSeries.dtype 现在是 SparseDtype 的实例,而不是 np.dtype。使用 SparseDtype.subtype 访问底层 dtype。

  • numpy.asarray(sparse_array) 现在返回包含所有值的密集数组,而不仅仅是非填充值(GH 14167

  • SparseArray.take 现在匹配 pandas.api.extensions.ExtensionArray.take() 的 API(GH 19506

    • allow_fill 的默认值从 False 更改为 True

    • outmode 参数不再被接受(以前如果指定这些参数会引发错误)。

    • 不再允许为 indices 传递标量。

  • concat() 混合使用稀疏和密集 Series 的结果是包含稀疏值的 Series,而不是 SparseSeries。

  • SparseDataFrame.combineDataFrame.combine_first 不再支持在保留稀疏子类型的同时将稀疏列与密集列组合。结果将是 object-dtype 的 SparseArray。

  • 现在允许将 SparseArray.fill_value 设置为具有不同 dtype 的填充值。

  • 当切片包含稀疏值的单列时,DataFrame[column] 现在是包含稀疏值的 Series,而不是 SparseSeries(GH 23559)。

  • Series.where() 的结果现在是包含稀疏值的 Series,与其他扩展数组类似(GH 24077)。

对于需要或可能实现大型密集数组的操作,会发出一些新的警告

  • 使用 method 参数调用 fillna 时,会发出 errors.PerformanceWarning 警告,因为需要构造一个密集数组来创建填充后的数组。使用 value 参数进行填充是填充稀疏数组的有效方法。

  • 当连接具有不同填充值的稀疏 Series 时,现在会发出 errors.PerformanceWarning 警告。连接结果将继续使用第一个稀疏数组的填充值。

除了这些 API 重大变更之外,还进行了许多性能改进和错误修复

最后,添加了一个 Series.sparse 访问器,以提供特定于稀疏数据的方法,例如 Series.sparse.from_coo()

In [67]: s = pd.Series([0, 0, 1, 1, 1], dtype='Sparse[int]')

In [68]: s.sparse.density
Out[68]: 0.6

get_dummies() 总是返回 DataFrame#

以前,当 sparse=True 参数传递给 get_dummies() 时,返回值可能是 DataFrameSparseDataFrame,取决于是否所有列或仅部分列被转换为哑变量。现在,总是返回一个 DataFrame (GH 24284)。

旧行为

第一个 get_dummies() 返回一个 DataFrame,因为列 A 没有被转换为哑变量。当只将 ["B", "C"] 传递给 get_dummies 时,所有列都被转换为哑变量,并且返回的是 SparseDataFrame

In [2]: df = pd.DataFrame({"A": [1, 2], "B": ['a', 'b'], "C": ['a', 'a']})

In [3]: type(pd.get_dummies(df, sparse=True))
Out[3]: pandas.core.frame.DataFrame

In [4]: type(pd.get_dummies(df[['B', 'C']], sparse=True))
Out[4]: pandas.core.sparse.frame.SparseDataFrame

新行为

现在,返回值类型始终是 DataFrame

In [69]: type(pd.get_dummies(df, sparse=True))
Out[69]: pandas.core.frame.DataFrame

In [70]: type(pd.get_dummies(df[['B', 'C']], sparse=True))
Out[70]: pandas.core.frame.DataFrame

注意

SparseDataFrame 和包含稀疏值的 DataFrame 在内存使用方面没有区别。内存使用量与之前版本的 pandas 相同。

DataFrame.to_dict(orient='index') 现在引发 ValueError#

DataFrame.to_dict() 的一个错误被修复,当与 orient='index' 和非唯一索引一起使用时,会引发 ValueError,而不是丢失数据 (GH 22801)

In [71]: df = pd.DataFrame({'a': [1, 2], 'b': [0.5, 0.75]}, index=['A', 'A'])

In [72]: df
Out[72]: 
   a     b
A  1  0.50
A  2  0.75

[2 rows x 2 columns]

In [73]: df.to_dict(orient='index')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[73], line 1
----> 1 df.to_dict(orient='index')

File ~/work/pandas/pandas/pandas/util/_decorators.py:333, in deprecate_nonkeyword_arguments.<locals>.decorate.<locals>.wrapper(*args, **kwargs)
    327 if len(args) > num_allow_args:
    328     warnings.warn(
    329         msg.format(arguments=_format_argument_list(allow_args)),
    330         FutureWarning,
    331         stacklevel=find_stack_level(),
    332     )
--> 333 return func(*args, **kwargs)

File ~/work/pandas/pandas/pandas/core/frame.py:2178, in DataFrame.to_dict(self, orient, into, index)
   2075 """
   2076 Convert the DataFrame to a dictionary.
   2077 
   (...)
   2174  defaultdict(<class 'list'>, {'col1': 2, 'col2': 0.75})]
   2175 """
   2176 from pandas.core.methods.to_dict import to_dict
-> 2178 return to_dict(self, orient, into=into, index=index)

File ~/work/pandas/pandas/pandas/core/methods/to_dict.py:242, in to_dict(df, orient, into, index)
    240 elif orient == "index":
    241     if not df.index.is_unique:
--> 242         raise ValueError("DataFrame index must be unique for orient='index'.")
    243     columns = df.columns.tolist()
    244     if are_all_object_dtype_cols:

ValueError: DataFrame index must be unique for orient='index'.

Tick DateOffset normalize 限制#

创建带有 normalize=True 参数的 Tick 对象(Day, Hour, Minute, Second, Milli, Micro, Nano)不再受支持。这可以防止加法操作可能无法保持单调性或结合性的意外行为 (GH 21427)

旧行为:

In [2]: ts = pd.Timestamp('2018-06-11 18:01:14')

In [3]: ts
Out[3]: Timestamp('2018-06-11 18:01:14')

In [4]: tic = pd.offsets.Hour(n=2, normalize=True)
   ...:

In [5]: tic
Out[5]: <2 * Hours>

In [6]: ts + tic
Out[6]: Timestamp('2018-06-11 00:00:00')

In [7]: ts + tic + tic + tic == ts + (tic + tic + tic)
Out[7]: False

新行为:

In [74]: ts = pd.Timestamp('2018-06-11 18:01:14')

In [75]: tic = pd.offsets.Hour(n=2)

In [76]: ts + tic + tic + tic == ts + (tic + tic + tic)
Out[76]: True

Period 减法#

一个 Period 减去另一个 Period 现在会得到一个 DateOffset 对象,而不是一个整数 (GH 21314)

旧行为:

In [2]: june = pd.Period('June 2018')

In [3]: april = pd.Period('April 2018')

In [4]: june - april
Out [4]: 2

新行为:

In [77]: june = pd.Period('June 2018')

In [78]: april = pd.Period('April 2018')

In [79]: june - april
Out[79]: <2 * MonthEnds>

类似地,PeriodIndex 减去一个 Period 现在会返回一个包含 DateOffset 对象的 Index,而不是 Int64Index

旧行为:

In [2]: pi = pd.period_range('June 2018', freq='M', periods=3)

In [3]: pi - pi[0]
Out[3]: Int64Index([0, 1, 2], dtype='int64')

新行为:

In [80]: pi = pd.period_range('June 2018', freq='M', periods=3)

In [81]: pi - pi[0]
Out[81]: Index([<0 * MonthEnds>, <MonthEnd>, <2 * MonthEnds>], dtype='object')

DataFrameNaN 进行加减操作#

timedelta64[ns] dtype 的 DataFrame 列添加或减去 NaN 现在会引发 TypeError,而不是返回全 NaT。这是为了与 TimedeltaIndexSeries 的行为兼容 (GH 22163)

In [82]: df = pd.DataFrame([pd.Timedelta(days=1)])

In [83]: df
Out[83]: 
       0
0 1 days

[1 rows x 1 columns]

旧行为:

In [4]: df = pd.DataFrame([pd.Timedelta(days=1)])

In [5]: df - np.nan
Out[5]:
    0
0 NaT

新行为:

In [2]: df - np.nan
...
TypeError: unsupported operand type(s) for -: 'TimedeltaIndex' and 'float'

DataFrame 比较操作广播行为变更#

以前,DataFrame 比较操作(==, !=, ...)的广播行为与算术操作(+, -, ...)的行为不一致。在这些情况下,比较操作的行为已更改为与算术操作匹配 (GH 22880)

受影响的情况是:

  • 与一维(一行或一列)的二维 np.ndarray 进行操作时,现在会像 np.ndarray 那样广播 (GH 23000)。

  • 长度与 DataFrame 行数匹配的列表或元组现在会引发 ValueError,而不是按列操作 (GH 22880

  • 长度与 DataFrame 列数匹配的列表或元组现在会按行操作,而不是引发 ValueError (GH 22880)。

In [84]: arr = np.arange(6).reshape(3, 2)

In [85]: df = pd.DataFrame(arr)

In [86]: df
Out[86]: 
   0  1
0  0  1
1  2  3
2  4  5

[3 rows x 2 columns]

旧行为:

In [5]: df == arr[[0], :]
    ...: # comparison previously broadcast where arithmetic would raise
Out[5]:
       0      1
0   True   True
1  False  False
2  False  False
In [6]: df + arr[[0], :]
...
ValueError: Unable to coerce to DataFrame, shape must be (3, 2): given (1, 2)

In [7]: df == (1, 2)
    ...: # length matches number of columns;
    ...: # comparison previously raised where arithmetic would broadcast
...
ValueError: Invalid broadcasting comparison [(1, 2)] with block values
In [8]: df + (1, 2)
Out[8]:
   0  1
0  1  3
1  3  5
2  5  7

In [9]: df == (1, 2, 3)
    ...:  # length matches number of rows
    ...:  # comparison previously broadcast where arithmetic would raise
Out[9]:
       0      1
0  False   True
1   True  False
2  False  False
In [10]: df + (1, 2, 3)
...
ValueError: Unable to coerce to Series, length must be 2: given 3

新行为:

# Comparison operations and arithmetic operations both broadcast.
In [87]: df == arr[[0], :]
Out[87]: 
       0      1
0   True   True
1  False  False
2  False  False

[3 rows x 2 columns]

In [88]: df + arr[[0], :]
Out[88]: 
   0  1
0  0  2
1  2  4
2  4  6

[3 rows x 2 columns]
# Comparison operations and arithmetic operations both broadcast.
In [89]: df == (1, 2)
Out[89]: 
       0      1
0  False  False
1  False  False
2  False  False

[3 rows x 2 columns]

In [90]: df + (1, 2)
Out[90]: 
   0  1
0  1  3
1  3  5
2  5  7

[3 rows x 2 columns]
# Comparison operations and arithmetic operations both raise ValueError.
In [6]: df == (1, 2, 3)
...
ValueError: Unable to coerce to Series, length must be 2: given 3

In [7]: df + (1, 2, 3)
...
ValueError: Unable to coerce to Series, length must be 2: given 3

DataFrame 算术操作广播行为变更#

DataFrame 算术操作与二维 np.ndarray 对象进行操作时,现在会像 np.ndarray 那样广播 (GH 23000)

In [91]: arr = np.arange(6).reshape(3, 2)

In [92]: df = pd.DataFrame(arr)

In [93]: df
Out[93]: 
   0  1
0  0  1
1  2  3
2  4  5

[3 rows x 2 columns]

旧行为:

In [5]: df + arr[[0], :]   # 1 row, 2 columns
...
ValueError: Unable to coerce to DataFrame, shape must be (3, 2): given (1, 2)
In [6]: df + arr[:, [1]]   # 1 column, 3 rows
...
ValueError: Unable to coerce to DataFrame, shape must be (3, 2): given (3, 1)

新行为:

In [94]: df + arr[[0], :]   # 1 row, 2 columns
Out[94]: 
   0  1
0  0  2
1  2  4
2  4  6

[3 rows x 2 columns]

In [95]: df + arr[:, [1]]   # 1 column, 3 rows
Out[95]: 
   0   1
0  1   2
1  5   6
2  9  10

[3 rows x 2 columns]

Series 和 Index 数据-dtype 不兼容#

SeriesIndex 构造函数在数据与传入的 dtype= 不兼容时现在会引发错误 (GH 15832)

旧行为:

In [4]: pd.Series([-1], dtype="uint64")
Out [4]:
0    18446744073709551615
dtype: uint64

新行为:

In [4]: pd.Series([-1], dtype="uint64")
Out [4]:
...
OverflowError: Trying to coerce negative values to unsigned integers

连接 (Concatenation) 变更#

对包含 NA 值的整型 Categorical 调用 pandas.concat() 时,如果与除另一个整型 Categorical 以外的任何对象连接,它们现在会被处理为对象 (GH 19214)

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

In [97]: c = pd.Series([0, 1, np.nan], dtype="category")

旧行为

In [3]: pd.concat([s, c])
Out[3]:
0    0.0
1    1.0
2    NaN
0    0.0
1    1.0
2    NaN
dtype: float64

新行为

In [98]: pd.concat([s, c])
Out[98]: 
0    0.0
1    1.0
2    NaN
0    0.0
1    1.0
2    NaN
Length: 6, dtype: float64

日期时间类似 (Datetimelike) API 变更#

其他 API 变更#

  • 新建的以整数作为 dtype 的空 DataFrame 现在只在指定了 index 时才会被转换为 float64 (GH 22858)

  • Series.str.cat() 现在在 othersset 时会引发错误 (GH 23009)

  • DatetimeIndexTimedeltaIndex 传递标量值现在会引发 TypeError,而不是 ValueError (GH 23539)

  • HTMLFormattermax_rowsmax_cols 参数已移除,因为截断功能由 DataFrameFormatter 处理 (GH 23818)

  • 如果声明为 bool dtype 的列包含缺失值,read_csv() 现在会引发 ValueError (GH 20591)

  • MultiIndex.to_frame() 获得的 DataFrame 的列顺序现在保证与 MultiIndex.names 的顺序一致 (GH 22420)

  • 错误地将 DatetimeIndex 传递给 MultiIndex.from_tuples()(而不是元组序列)现在会引发 TypeError,而不是 ValueError (GH 24024)

  • pd.offsets.generate_range() 的参数 time_rule 已被移除;请改用 offset (GH 24157)

  • 在 0.23.x 版本中,pandas 会在合并数值列(例如 int dtyped 列)和 object dtyped 列时引发 ValueError (GH 9780)。我们重新启用了合并 object 和其他 dtype 的功能;但在合并数值列和仅由字符串组成的 object dtyped 列时,pandas 仍会引发错误 (GH 21681)

  • 访问具有重复名称的 MultiIndex 级别(例如在 get_level_values() 中)现在会引发 ValueError,而不是 KeyError (GH 21678)。

  • 如果子 dtype 无效,无效的 IntervalDtype 构造现在始终会引发 TypeError,而不是 ValueError (GH 21185)

  • 尝试对具有非唯一 MultiIndexDataFrame 进行 reindex 现在会引发 ValueError,而不是 Exception (GH 21770)

  • Index 减法将尝试按元素操作,而不是引发 TypeError (GH 19369)

  • pandas.io.formats.style.Styler 在使用 to_excel() 时支持 number-format 属性 (GH 22015)

  • DataFrame.corr()Series.corr() 现在在提供了无效方法时会引发 ValueError 并附带一条有用的错误消息,而不是 KeyError (GH 22298)

  • shift() 现在总是返回一个副本,而不是之前的平移 0 时返回自身的行为 (GH 22397)

  • DataFrame.set_index() 现在在 Key 错误时提供更好的(且更少发生)信息,对错误类型引发 ValueError,并且在使用 drop=True 时不会因重复列名而失败 (GH 22484)

  • 对具有相同类型的多个 ExtensionArrays 的 DataFrame 切片单行时,现在会保留 dtype,而不是强制转换为对象 (GH 22784)

  • DateOffset 属性 _cacheable 和方法 _should_cache 已被移除 (GH 23118)

  • 当提供标量值进行搜索时,Series.searchsorted() 现在返回一个标量,而不是一个数组 (GH 23801)。

  • 当提供标量值进行搜索时,Categorical.searchsorted() 现在返回一个标量,而不是一个数组 (GH 23466)。

  • 如果搜索的键在其类别中未找到,Categorical.searchsorted() 现在会引发 KeyError,而不是 ValueError (GH 23466)。

  • Index.hasnans()Series.hasnans() 现在总是返回 Python 布尔值。以前,根据情况可能返回 Python 或 NumPy 布尔值 (GH 23294)。

  • DataFrame.to_html()DataFrame.to_string() 的参数顺序已调整以保持一致 (GH 23614)

  • 如果目标索引非唯一且不等于当前索引,CategoricalIndex.reindex() 现在会引发 ValueError。以前它只在目标索引不是 categorical dtype 时引发错误 (GH 23963)。

  • Series.to_list()Index.to_list() 现在分别是 Series.tolistIndex.tolist 的别名 (GH 8826)

  • SparseSeries.unstack 的结果现在是一个包含稀疏值的 DataFrame,而不是 SparseDataFrame (GH 24372)。

  • DatetimeIndexTimedeltaIndex 不再忽略 dtype 精度。传递非纳秒级精度的 dtype 将引发 ValueError (GH 24753)

扩展类型 (Extension type) 变更#

相等性 (Equality) 和可哈希性 (hashability)

pandas 现在要求扩展 dtype 必须是可哈希的(即相应的 ExtensionDtype 对象;对于相应的 ExtensionArray 的值,可哈希性不是必需的)。基类实现了默认的 __eq____hash__ 方法。如果您有参数化的 dtype,应更新 ExtensionDtype._metadata 元组以匹配您的 __init__ 方法的签名。更多信息请参见 pandas.api.extensions.ExtensionDtype (GH 22476)。

新增和修改的方法

Dtype 变更

  • ExtensionDtype 增加了从字符串 dtype 实例化的能力,例如 decimal 将实例化注册的 DecimalDtype;此外,ExtensionDtype 增加了方法 construct_array_type (GH 21185)

  • 新增 ExtensionDtype._is_numeric,用于控制扩展 dtype 是否被视为数值类型 (GH 22290)。

  • 新增 pandas.api.types.register_extension_dtype(),用于向 pandas 注册扩展类型 (GH 22664)。

  • 更新了 PeriodDtypeDatetimeTZDtypeIntervalDtype.type 属性,使其成为对应 dtype 的实例(分别为 PeriodTimestampInterval)(GH 22938)。

运算符支持

基于 ExtensionArraySeries 现在支持算术和比较运算符 (GH 19577)。为 ExtensionArray 提供运算符支持有两种方法:

  1. 在您的 ExtensionArray 子类上定义每个运算符。

  2. 使用 pandas 中依赖于 ExtensionArray 基础元素(标量)已定义运算符的运算符实现。

有关添加运算符支持这两种方法的详细信息,请参阅 ExtensionArray 运算符支持 文档部分。

其他更改

错误修复

弃用#

  • MultiIndex.labels 已弃用,并由 MultiIndex.codes 替代。功能保持不变。新名称更好地反映了这些 codes 的性质,并使 MultiIndex API 更类似于 CategoricalIndex 的 API (GH 13443)。因此,MultiIndex 中名称 labels 的其他用法也已弃用,并替换为 codes

    • 应使用名为 codes 而非 labels 的参数初始化 MultiIndex 实例。

    • MultiIndex.set_labels 已弃用,建议改用 MultiIndex.set_codes()

    • 对于方法 MultiIndex.copy()labels 参数已弃用,并由 codes 参数替代。

  • DataFrame.to_stata()read_stata()StataReaderStataWriter 已弃用 encoding 参数。Stata dta 文件的编码由文件类型决定,无法更改 (GH 21244)。

  • MultiIndex.to_hierarchical() 已弃用,并将在未来版本中移除 (GH 21613)。

  • Series.ptp() 已弃用。请改用 numpy.ptp (GH 21614)。

  • Series.compress() 已弃用。请改用 Series[condition] (GH 18262)。

  • Series.to_csv() 的签名已统一为与 DataFrame.to_csv() 相同:第一个参数的名称现在是 path_or_buf,后续参数的顺序已更改,header 参数现在默认为 True。(...) (GH 19715)。

  • Categorical.from_codes() 已弃用为 codes 参数提供浮点值 (GH 21767)。

  • pandas.read_table() 已弃用。请改用 read_csv(),如有必要,传递 sep='\t'。此弃用已在 0.25.0 版本中移除 (GH 21948)。

  • Series.str.cat() 已弃用在类列表对象内部使用任意类列表对象。类列表容器仍可以包含许多 SeriesIndex 或一维 np.ndarray,或者只包含标量值 (GH 21950)。

  • FrozenNDArray.searchsorted() 已弃用 v 参数,建议改用 value (GH 14645)。

  • DatetimeIndex.shift()PeriodIndex.shift() 现在接受 periods 参数而不是 n,以便与 Index.shift()Series.shift() 保持一致。使用 n 会引发弃用警告 (GH 22458, GH 22912)。

  • 不同 Index 构造函数的 fastpath 关键字已弃用 (GH 23110)。

  • Timestamp.tz_localize()DatetimeIndex.tz_localize()Series.tz_localize() 已弃用 errors 参数,建议改用 nonexistent 参数 (GH 8917)。

  • FrozenNDArray 已弃用。一旦此类被移除,反序列化时,FrozenNDArray 将被反序列化为 np.ndarray (GH 9031)。

  • 方法 DataFrame.update()Panel.update() 已弃用 raise_conflict=False|True 关键字,建议改用 errors='ignore'|'raise' (GH 23585)。

  • 方法 Series.str.partition()Series.str.rpartition() 已弃用 pat 关键字,建议改用 sep (GH 22676)。

  • 弃用 pandas.read_feather()nthreads 关键字,建议改用 use_threads,以反映 pyarrow>=0.11.0 中的更改 (GH 23053)。

  • pandas.read_excel() 已弃用接受整数作为 usecols。请改传递一个包含从 0 到 usecols(包括)的整数列表 (GH 23527)。

  • 从具有 datetime64 类型数据的数据构建 TimedeltaIndex 已弃用,将在未来版本中引发 TypeError (GH 23539)。

  • 从具有 timedelta64 类型数据的数据构建 DatetimeIndex 已弃用,将在未来版本中引发 TypeError (GH 23675)。

  • DatetimeIndex.to_series()keep_tz 关键字的 keep_tz=False 选项(默认值)已弃用 (GH 17832)。

  • 现在已弃用使用 Timestamptz 参数对 tz-aware 的 datetime.datetimeTimestamp 进行时区转换。请改用 Timestamp.tz_convert() (GH 23579)。

  • pandas.api.types.is_period() 已弃用,建议改用 pandas.api.types.is_period_dtype (GH 23917)。

  • pandas.api.types.is_datetimetz() 已弃用,建议改用 pandas.api.types.is_datetime64tz (GH 23917)。

  • 通过传递范围参数 startendperiods 来创建 TimedeltaIndexDatetimeIndexPeriodIndex 已弃用,建议改用 timedelta_range()date_range()period_range() (GH 23919)。

  • 已弃用将字符串别名(如 'datetime64[ns, UTC]')作为 unit 参数传递给 DatetimeTZDtype。请改用 DatetimeTZDtype.construct_from_string (GH 23990)。

  • infer_dtype()skipna 参数在未来版本的 pandas 中将默认切换为 True (GH 17066, GH 24050)。

  • 在使用 Categorical 数据的情况下,Series.where() 中提供不在类别中的 other 已弃用。请先将 Categorical 转换为不同的 dtype 或将 other 添加到类别中 (GH 24077)。

  • Series.clip_lower()Series.clip_upper()DataFrame.clip_lower()DataFrame.clip_upper() 已弃用,并将在未来版本中移除。请使用 Series.clip(lower=threshold)Series.clip(upper=threshold) 以及等效的 DataFrame 方法 (GH 24203)。

  • Series.nonzero() 已弃用,并将在未来版本中移除 (GH 18262)。

  • 已弃用在 timedelta64[ns] dtypes 的情况下将整数传递给 Series.fillna()DataFrame.fillna(),这将在未来版本中引发 TypeError。请改用 obj.fillna(pd.Timedelta(...)) (GH 24694)。

  • Series.cat.categoricalSeries.cat.nameSeries.cat.index 已弃用。请直接使用 Series.catSeries 上的属性 (GH 24751)。

  • 现在已弃用将没有精度(如 np.dtype('datetime64')timedelta64)的 dtype 传递给 IndexDatetimeIndexTimedeltaIndex。请改用纳秒精度 dtype (GH 24753)。

与 datetimes 和 timedeltas 的整数加/减运算已弃用#

过去,用户在某些情况下可以从 TimestampDatetimeIndexTimedeltaIndex 中加或减整数或整数类型数组。

此用法现已弃用。请改加或减对象 freq 属性的整数倍 (GH 21939, GH 23878)。

旧行为:

In [5]: ts = pd.Timestamp('1994-05-06 12:15:16', freq=pd.offsets.Hour())
In [6]: ts + 2
Out[6]: Timestamp('1994-05-06 14:15:16', freq='H')

In [7]: tdi = pd.timedelta_range('1D', periods=2)
In [8]: tdi - np.array([2, 1])
Out[8]: TimedeltaIndex(['-1 days', '1 days'], dtype='timedelta64[ns]', freq=None)

In [9]: dti = pd.date_range('2001-01-01', periods=2, freq='7D')
In [10]: dti + pd.Index([1, 2])
Out[10]: DatetimeIndex(['2001-01-08', '2001-01-22'], dtype='datetime64[ns]', freq=None)

新行为:

In [108]: ts = pd.Timestamp('1994-05-06 12:15:16', freq=pd.offsets.Hour())

In[109]: ts + 2 * ts.freq
Out[109]: Timestamp('1994-05-06 14:15:16', freq='H')

In [110]: tdi = pd.timedelta_range('1D', periods=2)

In [111]: tdi - np.array([2 * tdi.freq, 1 * tdi.freq])
Out[111]: TimedeltaIndex(['-1 days', '1 days'], dtype='timedelta64[ns]', freq=None)

In [112]: dti = pd.date_range('2001-01-01', periods=2, freq='7D')

In [113]: dti + pd.Index([1 * dti.freq, 2 * dti.freq])
Out[113]: DatetimeIndex(['2001-01-08', '2001-01-22'], dtype='datetime64[ns]', freq=None)

向 DatetimeIndex 传递整数数据和时区#

未来版本的 pandas 中,向 DatetimeIndex 传递整数数据和时区的行为将发生变化。以前,这些被解释为目标时区中的 wall time。未来,这些将被解释为 UTC 中的 wall time,然后转换为目标时区 (GH 24559)。

默认行为保持不变,但会发出警告

In [3]: pd.DatetimeIndex([946684800000000000], tz="US/Central")
/bin/ipython:1: FutureWarning:
    Passing integer-dtype data and a timezone to DatetimeIndex. Integer values
    will be interpreted differently in a future version of pandas. Previously,
    these were viewed as datetime64[ns] values representing the wall time
    *in the specified timezone*. In the future, these will be viewed as
    datetime64[ns] values representing the wall time *in UTC*. This is similar
    to a nanosecond-precision UNIX epoch. To accept the future behavior, use

        pd.to_datetime(integer_data, utc=True).tz_convert(tz)

    To keep the previous behavior, use

        pd.to_datetime(integer_data).tz_localize(tz)

 #!/bin/python3
 Out[3]: DatetimeIndex(['2000-01-01 00:00:00-06:00'], dtype='datetime64[ns, US/Central]', freq=None)

正如警告消息所解释的,通过指定整数值为 UTC,然后转换为最终时区来选择未来的行为

In [99]: pd.to_datetime([946684800000000000], utc=True).tz_convert('US/Central')
Out[99]: DatetimeIndex(['1999-12-31 18:00:00-06:00'], dtype='datetime64[ns, US/Central]', freq=None)

可以通过直接本地化到最终时区来保留旧的行为

In [100]: pd.to_datetime([946684800000000000]).tz_localize('US/Central')
Out[100]: DatetimeIndex(['2000-01-01 00:00:00-06:00'], dtype='datetime64[ns, US/Central]', freq=None)

将时区感知的 Series 和 Index 转换为 NumPy 数组#

从包含时区感知的 datetime 数据的 SeriesIndex 进行转换时,默认情况下将保留时区 (GH 23569)。

NumPy 没有用于时区感知 datetimes 的专用 dtype。过去,将包含时区感知 datatimes 的 SeriesDatetimeIndex 转换为 NumPy 数组会通过以下方式进行:

  1. 将 tz-aware 数据转换为 UTC

  2. 丢弃时区信息

  3. 返回一个具有 datetime64[ns] dtype 的 numpy.ndarray

未来版本的 pandas 将通过返回一个 object-dtype NumPy 数组来保留时区信息,该数组中的每个值都是带有正确附加时区的 Timestamp

In [101]: ser = pd.Series(pd.date_range('2000', periods=2, tz="CET"))

In [102]: ser
Out[102]: 
0   2000-01-01 00:00:00+01:00
1   2000-01-02 00:00:00+01:00
Length: 2, dtype: datetime64[ns, CET]

默认行为保持不变,但会发出警告

In [8]: np.asarray(ser)
/bin/ipython:1: FutureWarning: Converting timezone-aware DatetimeArray to timezone-naive
      ndarray with 'datetime64[ns]' dtype. In the future, this will return an ndarray
      with 'object' dtype where each element is a 'pandas.Timestamp' with the correct 'tz'.

        To accept the future behavior, pass 'dtype=object'.
        To keep the old behavior, pass 'dtype="datetime64[ns]"'.
  #!/bin/python3
Out[8]:
array(['1999-12-31T23:00:00.000000000', '2000-01-01T23:00:00.000000000'],
      dtype='datetime64[ns]')

通过指定 dtype,可以在没有任何警告的情况下获得以前或未来的行为

旧行为

In [103]: np.asarray(ser, dtype='datetime64[ns]')
Out[103]: 
array(['1999-12-31T23:00:00.000000000', '2000-01-01T23:00:00.000000000'],
      dtype='datetime64[ns]')

未来行为

# New behavior
In [104]: np.asarray(ser, dtype=object)
Out[104]: 
array([Timestamp('2000-01-01 00:00:00+0100', tz='CET'),
       Timestamp('2000-01-02 00:00:00+0100', tz='CET')], dtype=object)

或者使用 Series.to_numpy()

In [105]: ser.to_numpy()
Out[105]: 
array([Timestamp('2000-01-01 00:00:00+0100', tz='CET'),
       Timestamp('2000-01-02 00:00:00+0100', tz='CET')], dtype=object)

In [106]: ser.to_numpy(dtype="datetime64[ns]")
Out[106]: 
array(['1999-12-31T23:00:00.000000000', '2000-01-01T23:00:00.000000000'],
      dtype='datetime64[ns]')

上述所有内容也适用于具有 tz-aware 值的 DatetimeIndex

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

  • LongPanelWidePanel 已被移除 (GH 10892)。

  • Series.repeat() 已将 reps 参数重命名为 repeats (GH 14645)。

  • 从(非公开)模块 pandas.core.common 中移除了几个私有函数 (GH 22001)。

  • 移除了先前已弃用的模块 pandas.core.datetools (GH 14105, GH 14094)。

  • 传递给 DataFrame.groupby() 且同时引用列和索引级别的字符串将引发 ValueError (GH 14432)。

  • Index.repeat()MultiIndex.repeat() 已将参数 n 重命名为 repeats (GH 14645)

  • Series 构造函数和 .astype 方法现在将抛出 ValueError 错误,如果为 dtype 参数传入的时间戳 dtype 没有指定单元(例如 np.datetime64)(GH 15987)

  • 已从 str.match() 中完全移除先前弃用的 as_indexer 关键字 (GH 22356, GH 6581)

  • 模块 pandas.typespandas.computationpandas.util.decorators 已被移除 (GH 16157, GH 16250)

  • 已移除 pandas.io.formats.style.Stylerpandas.formats.style 垫片 (GH 16059)

  • pandas.pnowpandas.matchpandas.groupbypd.get_storepd.Exprpd.Term 已被移除 (GH 15538, GH 15940)

  • Categorical.searchsorted()Series.searchsorted() 已将参数 v 重命名为 value (GH 14645)

  • pandas.parserpandas.libpandas.tslib 已被移除 (GH 15537)

  • Index.searchsorted() 已将参数 key 重命名为 value (GH 14645)

  • DataFrame.consolidateSeries.consolidate 已被移除 (GH 15501)

  • 已移除先前弃用的模块 pandas.json (GH 19944)

  • 模块 pandas.tools 已被移除 (GH 15358, GH 16005)

  • SparseArray.get_values()SparseArray.to_dense() 已移除 fill 参数 (GH 14686)

  • DataFrame.sortlevelSeries.sortlevel 已被移除 (GH 15099)

  • SparseSeries.to_dense() 已移除 sparse_only 参数 (GH 14686)

  • DataFrame.astype()Series.astype() 已将参数 raise_on_error 重命名为 errors (GH 14967)

  • is_sequenceis_any_int_dtypeis_floating_dtype 已从 pandas.api.types 中移除 (GH 16163, GH 16189)

性能改进#

错误修复#

分类数据 (Categorical)#

  • Categorical.from_codes() 中存在一个错误,其中 codes 中的 NaN 值被静默转换为 0 (GH 21767)。将来这将抛出 ValueError 错误。还改变了 .from_codes([1.1, 2.0]) 的处理行为。

  • Categorical.sort_values() 中存在一个错误,其中 NaN 值总是被放在前面,无论 na_position 的值是什么。 (GH 22556)。

  • 使用布尔值的 Categorical 进行索引时存在一个错误。现在布尔值的 Categorical 被视为布尔掩码 (GH 22665)

  • 构造一个带有空值和布尔类别的 CategoricalIndex 在修改 dtype 强制转换后会抛出 ValueError 错误 (GH 22702)。

  • Categorical.take() 中存在一个错误,用户提供的 fill_value 没有正确编码该 fill_value,可能导致 ValueError 错误、结果不正确或段错误 (GH 23296)。

  • Series.unstack() 中,指定一个类别中不存在的 fill_value 现在会抛出 TypeError 错误,而不是忽略该 fill_value (GH 23284)

  • DataFrame.resample() 进行重采样并在 categorical 数据上聚合时存在一个错误,导致 categorical dtype 丢失。 (GH 23227)

  • .str-访问器的许多方法中存在一个错误,调用 CategoricalIndex.str 构造函数时总是失败 (GH 23555, GH 23556)

  • Series.where() 中存在一个错误,导致 categorical 数据丢失其 categorical dtype (GH 24077)

  • Categorical.apply() 中存在一个错误,其中 NaN 值可能被不可预测地处理。它们现在保持不变 (GH 24241)

  • Categorical 的比较方法中存在一个错误,对 DataFrame 进行操作时错误地抛出 ValueError 错误 (GH 24630)

  • Categorical.set_categories() 中存在一个错误,其中使用 rename=True 设置更少的新类别会导致段错误 (GH 24675)

日期时间类 (Datetimelike)#

  • 修复了两个具有不同 normalize 属性的 DateOffset 对象可能被评估为相等的一个错误 (GH 21404)

  • 修复了 Timestamp.resolution() 错误地返回 1 微秒 timedelta 的值,而不是 1 纳秒 Timedelta 的一个错误 (GH 21336, GH 21365)

  • to_datetime() 中存在一个错误,指定 box=True 时没有一致地返回 Index (GH 21864)

  • DatetimeIndex 的比较中存在一个错误,其中字符串比较错误地抛出 TypeError 错误 (GH 22074)

  • 与 dtype 为 timedelta64[ns] 的数组比较时,DatetimeIndex 的比较中存在一个错误;在某些情况下错误地抛出了 TypeError 错误,在其他情况下则错误地未抛出 (GH 22074)

  • 与 object-dtype 数组比较时,DatetimeIndex 的比较中存在一个错误 (GH 22074)

  • 类型为 datetime64[ns]DataFrameTimedelta 相似对象进行加减法运算时存在一个错误 (GH 22005, GH 22163)

  • 类型为 datetime64[ns]DataFrameDateOffset 对象进行加减法运算时,返回 object dtype 而不是 datetime64[ns] dtype 的一个错误 (GH 21610, GH 22163)

  • 类型为 datetime64[ns]DataFrameNaT 错误地进行比较时存在一个错误 (GH 22242, GH 22163)

  • 类型为 datetime64[ns]DataFrame 减去 Timestamp 相似对象时,错误地返回 datetime64[ns] dtype 而不是 timedelta64[ns] dtype 的一个错误 (GH 8554, GH 22163)

  • 类型为 datetime64[ns]DataFrame 减去非纳秒单位的 np.datetime64 对象时,未能转换为纳秒的一个错误 (GH 18874, GH 22163)

  • Timestamp 相似对象进行比较时,DataFrame 对于类型不匹配的不等式检查未能抛出 TypeError 错误中的一个错误 (GH 8932, GH 22163)

  • 包含 datetime64[ns] 的混合 dtype 的 DataFrame 中,对相等性进行比较时错误地抛出 TypeError 错误中的一个错误 (GH 13128, GH 22163)

  • DataFrame.values 中存在一个错误,对于包含感知时区日期时间值的单列 DataFrame,错误地返回了 DatetimeIndex。现在返回的是包含 Timestamp 对象的二维 numpy.ndarray (GH 24024)

  • NaT 比较时,DataFrame.eq() 错误地返回 TrueNaN 中的一个错误 (GH 15697, GH 22163)

  • DatetimeIndex 的减法运算中存在一个错误,错误地未能抛出 OverflowError 错误 (GH 22492, GH 22508)

  • DatetimeIndex 中存在一个错误,错误地允许使用 Timedelta 对象进行索引 (GH 20464)

  • DatetimeIndex 中的一个错误,如果原始频率为 None,则会设置频率 (GH 22150)

  • DatetimeIndex 的舍入方法(round()ceil()floor())和 Timestamp 的舍入方法(round()ceil()floor())中存在一个错误,可能导致精度丢失 (GH 22591)

  • to_datetime() 中存在一个错误,其中使用 Index 参数时会丢弃结果的 name 属性 (GH 21697)

  • PeriodIndex 中的一个错误,其中添加或减去 timedeltaTick 对象会产生错误结果 (GH 22988)

  • 类型为 period-dtype 的 Series 的 repr 中存在一个错误,数据前缺少一个空格 (GH 23601)

  • date_range() 中存在一个错误,通过负频率将开始日期递减到过去的结束日期时出错 (GH 23270)

  • Bug in Series.min() which would return NaN instead of NaT when called on a series of NaT (GH 23282)

  • Bug in Series.combine_first() not properly aligning categoricals, so that missing values in self where not filled by valid values from other (GH 24147)

  • Bug in DataFrame.combine() with datetimelike values raising a TypeError (GH 23079)

  • Bug in date_range() with frequency of Day or higher where dates sufficiently far in the future could wrap around to the past instead of raising OutOfBoundsDatetime (GH 14187)

  • Bug in period_range() ignoring the frequency of start and end when those are provided as Period objects (GH 20535).

  • Bug in PeriodIndex with attribute freq.n greater than 1 where adding a DateOffset object would return incorrect results (GH 23215)

  • Bug in Series that interpreted string indices as lists of characters when setting datetimelike values (GH 23451)

  • Bug in DataFrame when creating a new column from an ndarray of Timestamp objects with timezones creating an object-dtype column, rather than datetime with timezone (GH 23932)

  • Bug in Timestamp constructor which would drop the frequency of an input Timestamp (GH 22311)

  • Bug in DatetimeIndex where calling np.array(dtindex, dtype=object) would incorrectly return an array of long objects (GH 23524)

  • Bug in Index where passing a timezone-aware DatetimeIndex and dtype=object would incorrectly raise a ValueError (GH 23524)

  • Bug in Index where calling np.array(dtindex, dtype=object) on a timezone-naive DatetimeIndex would return an array of datetime objects instead of Timestamp objects, potentially losing nanosecond portions of the timestamps (GH 23524)

  • Bug in Categorical.__setitem__ not allowing setting with another Categorical when both are unordered and have the same categories, but in a different order (GH 24142)

  • Bug in date_range() where using dates with millisecond resolution or higher could return incorrect values or the wrong number of values in the index (GH 24110)

  • Bug in DatetimeIndex where constructing a DatetimeIndex from a Categorical or CategoricalIndex would incorrectly drop timezone information (GH 18664)

  • Bug in DatetimeIndex and TimedeltaIndex where indexing with Ellipsis would incorrectly lose the index’s freq attribute (GH 21282)

  • Clarified error message produced when passing an incorrect freq argument to DatetimeIndex with NaT as the first entry in the passed data (GH 11587)

  • Bug in to_datetime() where box and utc arguments were ignored when passing a DataFrame or dict of unit mappings (GH 23760)

  • Bug in Series.dt where the cache would not update properly after an in-place operation (GH 24408)

  • Bug in PeriodIndex where comparisons against an array-like object with length 1 failed to raise ValueError (GH 23078)

  • Bug in DatetimeIndex.astype(), PeriodIndex.astype() and TimedeltaIndex.astype() ignoring the sign of the dtype for unsigned integer dtypes (GH 24405).

  • Fixed bug in Series.max() with datetime64[ns]-dtype failing to return NaT when nulls are present and skipna=False is passed (GH 24265)

  • Bug in to_datetime() where arrays of datetime objects containing both timezone-aware and timezone-naive datetimes would fail to raise ValueError (GH 24569)

  • Bug in to_datetime() with invalid datetime format doesn’t coerce input to NaT even if errors='coerce' (GH 24763)

Timedelta#

  • Bug in DataFrame with timedelta64[ns] dtype division by Timedelta-like scalar incorrectly returning timedelta64[ns] dtype instead of float64 dtype (GH 20088, GH 22163)

  • Bug in adding a Index with object dtype to a Series with timedelta64[ns] dtype incorrectly raising (GH 22390)

  • Bug in multiplying a Series with numeric dtype against a timedelta object (GH 22390)

  • Bug in Series with numeric dtype when adding or subtracting an array or Series with timedelta64 dtype (GH 22390)

  • Bug in Index with numeric dtype when multiplying or dividing an array with dtype timedelta64 (GH 22390)

  • Bug in TimedeltaIndex incorrectly allowing indexing with Timestamp object (GH 20464)

  • Fixed bug where subtracting Timedelta from an object-dtyped array would raise TypeError (GH 21980)

  • Fixed bug in adding a DataFrame with all-timedelta64[ns] dtypes to a DataFrame with all-integer dtypes returning incorrect results instead of raising TypeError (GH 22696)

  • Bug in TimedeltaIndex where adding a timezone-aware datetime scalar incorrectly returned a timezone-naive DatetimeIndex (GH 23215)

  • Bug in TimedeltaIndex where adding np.timedelta64('NaT') incorrectly returned an all-NaT DatetimeIndex instead of an all-NaT TimedeltaIndex (GH 23215)

  • Bug in Timedelta and to_timedelta() have inconsistencies in supported unit string (GH 21762)

  • Bug in TimedeltaIndex division where dividing by another TimedeltaIndex raised TypeError instead of returning a Float64Index (GH 23829, GH 22631)

  • Bug in TimedeltaIndex comparison operations where comparing against non-Timedelta-like objects would raise TypeError instead of returning all-False for __eq__ and all-True for __ne__ (GH 24056)

  • Bug in Timedelta comparisons when comparing with a Tick object incorrectly raising TypeError (GH 24710)

Timezones#

偏移量#

  • FY5253 中的错误,其中日期偏移量在算术运算中可能错误地引发 AssertionError (GH 14774)

  • DateOffset 中的错误,其中接受并忽略了关键字参数 weekmilliseconds。现在传递这些参数将引发 ValueError (GH 19398)

  • DateOffset 添加到 DataFramePeriodIndex 时错误地引发 TypeError 的错误 (GH 23215)

  • 比较 DateOffset 对象与非 DateOffset 对象(特别是字符串)时的错误,其中引发 ValueError,而不是在相等检查时返回 False,在不相等检查时返回 True (GH 23524)

数值#

  • Series __rmatmul__ 中的错误,不支持矩阵向量乘法 (GH 21530)

  • factorize() 中的错误,read-only 数组会使其失败 (GH 12813)

  • 修复了 unique() 处理带符号零不一致的错误:对于某些输入,0.0 和 -0.0 被视为相等,对于某些输入则视为不同。现在它们对于所有输入都被视为相等 (GH 21866)

  • DataFrame.agg()DataFrame.transform()DataFrame.apply() 中的错误,其中当提供函数列表和 axis=1(例如 df.apply(['sum', 'mean'], axis=1))时,错误地引发了 TypeError。现在这三种方法都能正确执行此类计算。(GH 16679)。

  • Series 与 datetime-like 标量和数组比较时的错误 (GH 22074)

  • DataFrame 中 boolean dtype 与 integer 相乘时返回 object dtype 而不是 integer dtype 的错误 (GH 22047, GH 22163)

  • DataFrame.apply() 中的错误,其中当提供字符串参数以及额外的定位或关键字参数(例如 df.apply('sum', min_count=1))时,错误地引发了 TypeError (GH 22376)

  • DataFrame.astype() 转换为 extension dtype 时可能引发 AttributeError 的错误 (GH 22578)

  • 带有 timedelta64[ns] dtype 的 DataFrame 与带有 integer dtype 的 ndarray 进行算术运算时,错误地将 ndarray 视为 timedelta64[ns] dtype 的错误 (GH 23114)

  • 带有 object dtype 的 Series.rpow() 中,1 ** NA 返回 NaN 而不是 1 的错误 (GH 22922)。

  • Series.agg() 现在可以处理 numpy 中对 NaN 感知的方法,例如 numpy.nansum() (GH 19629)

  • Series.rank()DataFrame.rank() 中的错误,其中当 pct=True 且存在超过 224 行时,导致百分比大于 1.0 (GH 18271)

  • 使用非唯一 CategoricalIndex() 调用 DataFrame.round() 等方法现在会返回预期数据。之前,数据会被错误地复制 (GH 21809)。

  • log10floorceil 添加到 DataFrame.eval() 支持的函数列表中 (GH 24139, GH 24353)

  • SeriesIndex 之间的逻辑运算 &, |, ^ 将不再引发 ValueError (GH 22092)

  • is_scalar() 函数中检查 PEP 3141 数字时返回 True (GH 22903)

  • Series.sum() 等归约方法现在在从 NumPy ufunc 调用时接受 keepdims=False 的默认值,而不是引发 TypeError。尚未实现对 keepdims 的完全支持 (GH 24356)。

转换#

  • DataFrame.combine_first() 中的错误,其中列类型被意外地转换为 float (GH 20699)

  • DataFrame.clip() 中的错误,其中列类型未保留并被转换为 float (GH 24162)

  • DataFrame.clip() 中的错误,其中当 DataFrames 的列顺序不匹配时,观察到的结果在数值上是错误的 (GH 20911)

  • DataFrame.astype() 中的错误,其中当存在重复列名时转换为 extension dtype 会导致 RecursionError (GH 24704)

字符串#

  • Index.str.partition() 中的错误,不是 nan-safe 的 (GH 23558)。

  • Index.str.split() 中的错误,不是 nan-safe 的 (GH 23677)。

  • Series.str.contains() 未遵守 Categorical dtype Seriesna 参数的错误 (GH 22158)

  • Index.str.cat() 中的错误,其中结果只包含 NaN (GH 24044)

区间#

  • IntervalIndex 构造函数中的错误,其中 closed 参数并非总是覆盖推断的 closed (GH 19370)

  • IntervalIndex repr 中的错误,其中区间列表后缺少尾随逗号 (GH 20611)

  • Interval 中的错误,其中标量算术运算未保留 closed 值 (GH 22313)

  • IntervalIndex 中的错误,其中使用 datetime-like 值进行索引时引发了 KeyError (GH 20636)

  • IntervalTree 中的错误,其中包含 NaN 的数据触发了警告,并导致使用 IntervalIndex 的索引查询不正确 (GH 23352)

索引#

  • DataFrame.ne() 中的错误,如果列中包含列名“dtype”,则会失败 (GH 22383)

  • 使用 .loc 查询单个缺失标签时,KeyError 的 traceback 现在更短、更清晰 (GH 21557)

  • PeriodIndex 现在在查找格式错误的字符串时会发出 KeyError,这与 DatetimeIndex 的行为一致 (GH 22803)

  • .ix 在第一级为整数类型的 MultiIndex 中查询缺失的整数标签时,现在会引发 KeyError,这与平坦的 Int64Index 情况一致,而不是回退到位置索引 (GH 21593)

  • Index.reindex() 中的错误,其中重新索引 tz-naive 和 tz-aware DatetimeIndex 时出现问题 (GH 8306)

  • Series.reindex() 中的错误,其中重新索引具有 datetime64[ns, tz] dtype 的空 Series 时出现问题 (GH 20869)

  • DataFrame 中的错误,其中使用 .loc 和时区感知的 DatetimeIndex 设置值时出现问题 (GH 11365)

  • DataFrame.__getitem__ 现在接受字典和字典键作为标签的 list-like,这与 Series.__getitem__ 一致 (GH 21294)

  • 修复了列非唯一时 DataFrame[np.nan] 的问题 (GH 21428)

  • 使用纳秒精度日期和时区索引 DatetimeIndex 时的错误 (GH 11679)

  • 使用包含负值的 Numpy 数组进行索引时会修改索引器的错误 (GH 21867)

  • 混合索引不允许将整数用于 .at 的错误 (GH 19860)

  • Float64Index.get_loc 在传递布尔键时现在会引发 KeyError。(GH 19087)。

  • DataFrame.loc() 中的错误,其中使用 IntervalIndex 进行索引时出现问题 (GH 19977)

  • Index 不再混淆 NoneNaNNaT,即将它们视为三个不同的键。但是,对于数值型 Index,这三者仍然会被强制转换为 NaN (GH 22332)

  • 如果标量是 float,而 Index 是 integer dtype 时的 scalar in Index 错误 (GH 22085)

  • MultiIndex.set_levels() 中的错误,其中 levels 值不可订阅 (GH 23273)

  • 通过 Index 设置 timedelta 列时导致其被转换为 double,从而损失精度的错误 (GH 23511)

  • Index.union()Index.intersection() 中的错误,其中在某些情况下结果 Index 的名称计算不正确 (GH 9943, GH 9862)

  • 使用布尔 IndexIndex 进行切片时可能引发 TypeError 的错误 (GH 22533)

  • PeriodArray.__setitem__ 中的错误,其中接受 slice 和 list-like 值时出现问题 (GH 23978)

  • DatetimeIndexTimedeltaIndex 中的错误,其中使用 Ellipsis 进行索引会丢失其 freq 属性 (GH 21282)

  • iat 中的错误,其中使用它分配不兼容的值会创建新列 (GH 23236)

缺失值#

  • DataFrame.fillna() 中的错误,其中当一列包含 datetime64[ns, tz] dtype 时会引发 ValueError (GH 15522)

  • Series.hasnans() 中的错误,如果初始调用后引入了空元素,该错误可能被错误缓存并返回不正确的结果 (GH 19700)

  • Series.isin() 现在对 np.object_-dtype 也将所有 NaN-float 视为相等。此行为与 float64 的行为一致 (GH 22119)

  • unique() 对于 np.object_-dtype 类型不再破坏 NaN-floats 和 NaT 对象,即 NaT 不再被强制转换为 NaN 值,而是被视为一个不同的实体。 (GH 22295)

  • DataFrameSeries 现在可以正确处理带有硬掩码 (hardened masks) 的 numpy 掩码数组。此前,从带有硬掩码的掩码数组构造 DataFrame 或 Series 会创建一个包含底层值的 pandas 对象,而不是预期的 NaN。 (GH 24574)

  • 在处理 numpy 掩码记录数组时,DataFrame 构造函数中存在一个 bug,该 bug 导致 dtype 参数未被遵循。 (GH 24874)

MultiIndex#

IO#

  • read_csv() 中存在一个 bug,该 bug 导致指定为具有布尔类别的 CategoricalDtype 的列无法正确地从字符串值强制转换为布尔值。 (GH 20498)

  • read_csv() 中存在一个 bug,该 bug 导致 unicode 列名在 Python 2.x 中无法被正确识别。 (GH 13253)

  • DataFrame.to_sql() 写入时区感知数据(datetime64[ns, tz] dtype)时,会引发 TypeError 的 bug。 (GH 9086)

  • DataFrame.to_sql() 中存在一个 bug,该 bug 导致 naive(非时区感知)的 DatetimeIndex 在支持的数据库(例如 PostgreSQL)中被写入为 TIMESTAMP WITH TIMEZONE 类型。 (GH 23510)

  • read_excel() 中存在一个 bug,当使用空数据集指定 parse_cols 时出现问题。 (GH 9208)

  • read_html() 在考虑 skiprowsheader 参数时,不再忽略 <thead> 内的仅包含空白字符的 <tr>。此前,用户必须在这些表格上减小 headerskiprows 值来解决此问题。 (GH 21641)

  • read_excel() 将正确显示先前已弃用的 sheetname 的弃用警告。 (GH 17994)

  • read_csv()read_table() 在遇到编码错误的字符串时将抛出 UnicodeError,而不是 core dump。 (GH 22748)

  • read_csv() 将正确解析时区感知日期时间。 (GH 22256)

  • read_csv() 的 C 引擎中存在一个 bug,当数据以块为单位读取时,由于完成或错误时的清理不足,解析 NaN 值时会发生内存泄漏。 (GH 21353)

  • read_csv() 中存在一个 bug,在提取多层索引时,未命名的列会被错误地识别。 (GH 23687)

  • read_sas() 将正确解析 sas7bdat 文件中宽度小于 8 字节的数字。 (GH 21616)

  • read_sas() 将正确解析包含许多列的 sas7bdat 文件。 (GH 22628)

  • read_sas() 将正确解析数据页类型设置了 bit 7 的 sas7bdat 文件(因此页类型为 128 + 256 = 384)。 (GH 16615)

  • read_sas() 中存在一个 bug,该 bug 导致在遇到无效文件格式时抛出了不正确的错误。 (GH 24548)

  • detect_client_encoding() 中存在一个 bug,该 bug 导致在 mod_wsgi 进程中导入时,由于对 stdout 的访问受限,潜在的 IOError 未被处理。 (GH 21552)

  • DataFrame.to_html() 中存在一个 bug,该 bug 导致当 index=False 时,在截断的 DataFrame 上缺少截断指示符 (...)。 (GH 15019, GH 22783)

  • DataFrame.to_html() 中存在一个 bug,该 bug 导致当 index=False 且列和行索引都是 MultiIndex 时出现问题。 (GH 22579)

  • DataFrame.to_html() 中存在一个 bug,该 bug 导致当 index_names=False 时仍然显示索引名称。 (GH 22747)

  • DataFrame.to_html() 中存在一个 bug,该 bug 导致当 header=False 时不显示行索引名称。 (GH 23788)

  • DataFrame.to_html() 中存在一个 bug,该 bug 导致当 sparsify=False 时引发 TypeError。 (GH 22887)

  • DataFrame.to_string() 中存在一个 bug,该 bug 导致当 index=False 且第一列值的宽度大于第一列标题的宽度时,列对齐被破坏。 (GH 16839, GH 13032)

  • DataFrame.to_string() 中存在一个 bug,该 bug 导致 DataFrame 的表示形式无法占据整个窗口。 (GH 22984)

  • DataFrame.to_csv() 中存在一个 bug,该 bug 导致单层 MultiIndex 错误地写入一个元组。现在只写入索引的值。 (GH 19589).

  • HDFStore 在构造函数中传入 format kwarg 时将引发 ValueError。 (GH 13291)

  • HDFStore.append() 中存在一个 bug,该 bug 导致在附加包含空字符串列且 min_itemsize < 8 的 DataFrame 时出现问题。 (GH 12242)

  • read_csv() 的 C 引擎中存在一个 bug,由于完成或错误时清理不足,解析 NaN 值时会发生内存泄漏。 (GH 21353)

  • read_csv() 中存在一个 bug,该 bug 导致当传入 skipfooter 以及 nrows, iteratorchunksize 时,会抛出不正确的错误消息。 (GH 23711)

  • read_csv() 中存在一个 bug,该 bug 导致在未提供 MultiIndex 索引名称的情况下,索引名称被错误地处理。 (GH 23484)

  • read_csv() 中存在一个 bug,该 bug 导致当 dialect 的值与默认参数冲突时,会抛出不必要的警告。 (GH 23761)

  • read_html() 中存在一个 bug,该 bug 导致在提供了无效 flavors 时,错误消息没有显示有效的 flavors。 (GH 23549)

  • read_excel() 中存在一个 bug,该 bug 导致即使没有指定标题名称,也会提取多余的标题名称。 (GH 11733)

  • read_excel() 中存在一个 bug,该 bug 导致在 Python 2.x 中,列名有时无法被正确转换为字符串。 (GH 23874)

  • read_excel() 中存在一个 bug,该 bug 导致 index_col=None 未被遵守,仍然解析索引列。 (GH 18792, GH 20480)

  • read_excel() 中存在一个 bug,该 bug 导致当 usecols 以字符串形式传入时,不会验证其是否为正确的列名。 (GH 20480)

  • DataFrame.to_dict() 中存在一个 bug,该 bug 导致在数值数据的情况下,生成的 dict 包含非 Python 标量。 (GH 23753)

  • DataFrame.to_string(), DataFrame.to_html(), DataFrame.to_latex() 将正确格式化输出,当字符串作为 float_format 参数传入时。 (GH 21625, GH 22270)

  • read_csv() 中存在一个 bug,该 bug 导致当尝试使用 'inf' 作为整数索引列的 na_value 时引发 OverflowError。 (GH 17128)

  • read_csv() 中存在一个 bug,该 bug 导致在 Windows 上使用 Python 3.6+ 的 C 引擎无法正确读取包含重音或特殊字符的 CSV 文件名。 (GH 15086)

  • read_fwf() 中存在一个 bug,该 bug 导致无法正确推断文件的压缩类型。 (GH 22199)

  • pandas.io.json.json_normalize() 中存在一个 bug,该 bug 导致当 record_path 中的两个连续元素是 dict 时引发 TypeError。 (GH 22706)

  • DataFrame.to_stata(), pandas.io.stata.StataWriterpandas.io.stata.StataWriter117 中存在一个 bug,该 bug 导致异常会留下一个部分写入的无效 dta 文件。 (GH 23573)

  • DataFrame.to_stata()pandas.io.stata.StataWriter117 中存在一个 bug,该 bug 导致在使用包含非 ASCII 字符的 strLs 时生成无效文件。 (GH 23573)

  • HDFStore 中存在一个 bug,该 bug 导致在 Python 3 中读取从 Python 2 以固定格式写入的 DataFrame 时引发 ValueError。 (GH 24510)

  • DataFrame.to_string() 和更一般的浮点 repr 格式化程序中存在一个 bug。当列中存在 inf 时,零不会被修剪,而在存在 NA 值时会修剪零。现在在存在 NA 的情况下也会修剪零。 (GH 24861)。

  • 在截断列数且最后一列较宽时,repr 中存在一个 bug。 (GH 24849)。

Plotting#

  • DataFrame.plot.scatter()DataFrame.plot.hexbin() 中存在一个 bug,该 bug 导致在 IPython inline 后端开启 colorbar 时,x 轴标签和刻度标签消失。 (GH 10611, GH 10678, and GH 20455)

  • 在使用 matplotlib.axes.Axes.scatter() 绘制带有日期时间的 Series 时存在一个 bug。 (GH 22039)

  • DataFrame.plot.bar() 中存在一个 bug,该 bug 导致条形图使用多种颜色而不是单一颜色。 (GH 20585)

  • 验证颜色参数时存在一个 bug,该 bug 导致额外的颜色被附加到给定的颜色数组中。这发生在多个使用 matplotlib 的绘图函数中。 (GH 20726)

GroupBy/resample/rolling#

  • Rolling.min()Rolling.max() 中存在一个 bug,该 bug 在使用 closed='left'、datetime 索引且 Series 中只有一条记录时,会导致 segfault。 (GH 24718)

  • GroupBy.first()GroupBy.last() 中存在一个 bug,该 bug 在使用 as_index=False 时会导致时区信息丢失。 (GH 15884)

  • DateFrame.resample() 跨 DST 边界降采样时存在一个 bug。 (GH 8531)

  • DateFrame.resample() 使用偏移量 Day 且 n > 1 时,日期锚定存在一个 bug。 (GH 24127)

  • 当分组变量仅包含 NaNs 且 numpy 版本小于 1.13 时,调用 SeriesGroupBy.count() 方法会错误地引发 ValueError 的 bug。 (GH 21956)。

  • Rolling.min() 中存在多个 bug,该 bug 在使用 closed='left' 和 datetime 索引时,会导致结果不正确,甚至 segfault。 (GH 21704)

  • Resampler.apply() 调用时将位置参数传递给应用函数存在一个 bug。 (GH 14615)。

  • Series.resample() 中存在一个 bug,该 bug 导致在将 numpy.timedelta64 传递给 loffset kwarg 时出现问题。 (GH 7687)。

  • Resampler.asfreq() 中存在一个 bug,该 bug 导致当 TimedeltaIndex 的频率是新频率的子周期时出现问题。 (GH 13022)。

  • SeriesGroupBy.mean() 中存在一个 bug,该 bug 导致当值是整数但无法放入 int64 而溢出时出现问题。 (GH 22487)

  • RollingGroupby.agg()ExpandingGroupby.agg() 现在支持将多个聚合函数作为参数。 (GH 15072)

  • DataFrame.resample()Series.resample() 中存在一个 bug,该 bug 导致在使用每周偏移量('W')跨 DST 过渡进行重采样时出现问题。 (GH 9119, GH 21459)

  • DataFrame.expanding() 中存在一个 bug,该 bug 导致在聚合期间不遵循 axis 参数。 (GH 23372)

  • GroupBy.transform() 中存在一个 bug,该 bug 导致当输入函数可以接受 DataFrame 但将其重命名时,会出现缺失值。 (GH 23455)。

  • GroupBy.nth() 中存在一个 bug,该 bug 导致列顺序并非总是保留。 (GH 20760)

  • GroupBy.rank() 中存在一个 bug,该 bug 导致当使用 method='dense'pct=True 且一个组中只有一个成员时,会引发 ZeroDivisionError。 (GH 23666)。

  • 在调用 GroupBy.rank() 时,当使用空组和 pct=True 时,会引发 ZeroDivisionError。 (GH 22519)

  • DataFrame.resample() 中存在一个 bug,该 bug 导致在 TimeDeltaIndex 中重采样 NaT 时出现问题。 (GH 13223).

  • DataFrame.groupby() 中存在一个 bug,该 bug 导致在选择列时未遵循 observed 参数,而是始终使用 observed=False。 (GH 23970)

  • SeriesGroupBy.pct_change()DataFrameGroupBy.pct_change() 中存在一个 bug,该 bug 此前会在计算百分比变化时跨组工作,现在则正确地按组工作。 (GH 21200, GH 21235).

  • 阻止创建具有非常大行数 (2^32) 的哈希表的 Bug (GH 22805)

  • 在使用分类数据进行 groupby 分组时,如果 observed=True 且分类列中存在 nan,会导致 ValueError 和不正确的分组的 Bug (GH 24740, GH 21151)。

重塑#

稀疏#

  • 现在可以将布尔、datetime 或 timedelta 列更新为稀疏列 (GH 22367)

  • 使用已经包含稀疏数据的 Series 调用 Series.to_sparse() 时构造不正确的 Bug (GH 22389)

  • 向 SparseArray 构造函数提供 sparse_index 不再将所有 dtype 的 na-value 默认设置为 np.nan。现在使用 data.dtype 的正确 na_value。

  • SparseArray.nbytes 中的 Bug,它通过不包含其稀疏索引的大小来少报内存使用量。

  • 对于非 NA fill_valueSeries.shift() 的性能得到改进,因为值不再转换为密集数组。

  • 在使用非 NA fill_value 按稀疏列分组时,DataFrame.groupby 中未将 fill_value 包含在组中的 Bug (GH 5078)

  • 在布尔值的 SparseSeries 上使用一元反演运算符 (~) 时出现的 Bug。该操作的性能也得到了改进 (GH 22835)

  • SparseArary.unique() 中未返回唯一值的 Bug (GH 19595)

  • SparseArray.nonzero()SparseDataFrame.dropna() 中返回偏移/不正确结果的 Bug (GH 21172)

  • DataFrame.apply() 中的 Bug,在该 Bug 中 dtype 会失去稀疏性 (GH 23744)

  • 在连接包含全稀疏值的 Series 列表时,concat() 中的 Bug 会改变 fill_value 并转换为密集 Series (GH 24371)

样式#

  • background_gradient() 现在接受 text_color_threshold 参数,可以根据背景颜色的亮度自动调整文本颜色。这提高了在深色背景下的可读性,而无需限制背景颜色映射范围。(GH 21258)

  • background_gradient() 现在也支持表格级别的应用(除了行级别和列级别),通过设置 axis=None (GH 15204)

  • bar() 现在也支持表格级别的应用(除了行级别和列级别),通过设置 axis=None 以及使用 vminvmax 设置剪切范围 (GH 21548GH 21526)。NaN 值现在也能正确处理。

构建更改#

  • 现在开发构建 pandas 需要 cython >= 0.28.2 (GH 21688)

  • 现在测试 pandas 需要 hypothesis>=3.58。你可以在这里找到 Hypothesis 文档,以及贡献指南中关于 pandas 的具体介绍。(GH 22280)

  • 现在如果在 macOS 10.9 或更高版本上构建 pandas,则最低支持 macOS 10.9 (GH 23424)

其他#

  • Bug:其中 C 变量声明为外部链接,如果在 pandas 之前导入了某些其他 C 库,则会导致导入错误。(GH 24113)

贡献者#

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

  • AJ Dyka +

  • AJ Pryor, Ph.D +

  • Aaron Critchley

  • Adam Hooper

  • Adam J. Stewart

  • Adam Kim

  • Adam Klimont +

  • Addison Lynch +

  • Alan Hogue +

  • Alex Radu +

  • Alex Rychyk

  • Alex Strick van Linschoten +

  • Alex Volkov +

  • Alexander Buchkovsky

  • Alexander Hess +

  • Alexander Ponomaroff +

  • Allison Browne +

  • Aly Sivji

  • Andrew

  • Andrew Gross +

  • Andrew Spott +

  • Andy +

  • Aniket uttam +

  • Anjali2019 +

  • Anjana S +

  • Antti Kaihola +

  • Anudeep Tubati +

  • Arjun Sharma +

  • Armin Varshokar

  • Artem Bogachev

  • ArtinSarraf +

  • Barry Fitzgerald +

  • Bart Aelterman +

  • Ben James +

  • Ben Nelson +

  • Benjamin Grove +

  • Benjamin Rowell +

  • Benoit Paquet +

  • Boris Lau +

  • Brett Naul

  • Brian Choi +

  • C.A.M. Gerlach +

  • Carl Johan +

  • Chalmer Lowe

  • Chang She

  • Charles David +

  • Cheuk Ting Ho

  • Chris

  • Chris Roberts +

  • Christopher Whelan

  • Chu Qing Hao +

  • Da Cheezy Mobsta +

  • Damini Satya

  • Daniel Himmelstein

  • Daniel Saxton +

  • Darcy Meyer +

  • DataOmbudsman

  • David Arcos

  • David Krych

  • Dean Langsam +

  • Diego Argueta +

  • Diego Torres +

  • Dobatymo +

  • Doug Latornell +

  • Dr. Irv

  • Dylan Dmitri Gray +

  • Eric Boxer +

  • Eric Chea

  • Erik +

  • Erik Nilsson +

  • Fabian Haase +

  • Fabian Retkowski

  • Fabien Aulaire +

  • Fakabbir Amin +

  • Fei Phoon +

  • Fernando Margueirat +

  • Florian Müller +

  • Fábio Rosado +

  • Gabe Fernando

  • Gabriel Reid +

  • Giftlin Rajaiah

  • Gioia Ballin +

  • Gjelt

  • Gosuke Shibahara +

  • Graham Inggs

  • Guillaume Gay

  • Guillaume Lemaitre +

  • Hannah Ferchland

  • Haochen Wu

  • Hubert +

  • HubertKl +

  • HyunTruth +

  • Iain Barr

  • Ignacio Vergara Kausel +

  • Irv Lustig +

  • IsvenC +

  • Jacopo Rota

  • Jakob Jarmar +

  • James Bourbeau +

  • James Myatt +

  • James Winegar +

  • Jan Rudolph

  • Jared Groves +

  • Jason Kiley +

  • Javad Noorbakhsh +

  • Jay Offerdahl +

  • Jeff Reback

  • Jeongmin Yu +

  • Jeremy Schendel

  • Jerod Estapa +

  • Jesper Dramsch +

  • Jim Jeon +

  • Joe Jevnik

  • Joel Nothman

  • Joel Ostblom +

  • Jordi Contestí

  • Jorge López Fueyo +

  • Joris Van den Bossche

  • Jose Quinones +

  • Jose Rivera-Rubio +

  • Josh

  • Jun +

  • Justin Zheng +

  • Kaiqi Dong +

  • Kalyan Gokhale

  • Kang Yoosam +

  • Karl Dunkle Werner +

  • Karmanya Aggarwal +

  • Kevin Markham +

  • Kevin Sheppard

  • Kimi Li +

  • Koustav Samaddar +

  • Krishna +

  • Kristian Holsheimer +

  • Ksenia Gueletina +

  • Kyle Prestel +

  • LJ +

  • LeakedMemory +

  • Li Jin +

  • Licht Takeuchi

  • Luca Donini +

  • Luciano Viola +

  • Mak Sze Chun +

  • Marc Garcia

  • Marius Potgieter +

  • Mark Sikora +

  • Markus Meier +

  • Marlene Silva Marchena +

  • Martin Babka +

  • MatanCohe +

  • Mateusz Woś +

  • Mathew Topper +

  • Matt Boggess +

  • Matt Cooper +

  • Matt Williams +

  • Matthew Gilbert

  • Matthew Roeschke

  • Max Kanter

  • Michael Odintsov

  • Michael Silverstein +

  • Michael-J-Ward +

  • Mickaël Schoentgen +

  • Miguel Sánchez de León Peque +

  • Ming Li

  • Mitar

  • Mitch Negus

  • Monson Shao +

  • Moonsoo Kim +

  • Mortada Mehyar

  • Myles Braithwaite

  • Nehil Jain +

  • Nicholas Musolino +

  • Nicolas Dickreuter +

  • Nikhil Kumar Mengani +

  • Nikoleta Glynatsi +

  • Ondrej Kokes

  • Pablo Ambrosio +

  • Pamela Wu +

  • Parfait G +

  • Patrick Park +

  • Paul

  • Paul Ganssle

  • Paul Reidy

  • Paul van Mulbregt +

  • Phillip Cloud

  • Pietro Battiston

  • Piyush Aggarwal +

  • Prabakaran Kumaresshan +

  • Pulkit Maloo

  • Pyry Kovanen

  • Rajib Mitra +

  • Redonnet Louis +

  • Rhys Parry +

  • Rick +

  • Robin

  • Roei.r +

  • RomainSa +

  • Roman Imankulov +

  • Roman Yurchak +

  • Ruijing Li +

  • Ryan +

  • Ryan Nazareth +

  • Rüdiger Busche +

  • SEUNG HOON, SHIN +

  • Sandrine Pataut +

  • Sangwoong Yoon

  • Santosh Kumar +

  • Saurav Chakravorty +

  • Scott McAllister +

  • Sean Chan +

  • Shadi Akiki +

  • Shengpu Tang +

  • Shirish Kadam +

  • Simon Hawkins +

  • Simon Riddell +

  • Simone Basso

  • Sinhrks

  • Soyoun(Rose) Kim +

  • Srinivas Reddy Thatiparthy (శ్రీనివాస్ రెడ్డి తాటిపర్తి) +

  • Stefaan Lippens +

  • Stefano Cianciulli

  • Stefano Miccoli +

  • Stephen Childs

  • Stephen Pascoe

  • Steve Baker +

  • Steve Cook +

  • Steve Dower +

  • Stéphan Taljaard +

  • Sumin Byeon +

  • Sören +

  • Tamas Nagy +

  • Tanya Jain +

  • Tarbo Fukazawa

  • Thein Oo +

  • Thiago Cordeiro da Fonseca +

  • Thierry Moisan

  • Thiviyan Thanapalasingam +

  • Thomas Lentali +

  • Tim D. Smith +

  • Tim Swast

  • Tom Augspurger

  • Tomasz Kluczkowski +

  • Tony Tao +

  • Triple0 +

  • Troels Nielsen +

  • Tuhin Mahmud +

  • Tyler Reddy +

  • Uddeshya Singh

  • Uwe L. Korn +

  • Vadym Barda +

  • Varad Gunjal +

  • Victor Maryama +

  • Victor Villas

  • Vincent La

  • Vitória Helena +

  • Vu Le

  • Vyom Jain +

  • Weiwen Gu +

  • Wenhuan

  • Wes Turner

  • Wil Tan +

  • William Ayd

  • Yeojin Kim +

  • Yitzhak Andrade +

  • Yuecheng Wu +

  • Yuliya Dovzhenko +

  • Yury Bayda +

  • Zac Hatfield-Dodds +

  • aberres +

  • aeltanawy +

  • ailchau +

  • alimcmaster1

  • alphaCTzo7G +

  • amphy +

  • araraonline +

  • azure-pipelines[bot] +

  • benarthur91 +

  • bk521234 +

  • cgangwar11 +

  • chris-b1

  • cxl923cc +

  • dahlbaek +

  • dannyhyunkim +

  • darke-spirits +

  • david-liu-brattle-1

  • davidmvalente +

  • deflatSOCO

  • doosik_bae +

  • dylanchase +

  • eduardo naufel schettino +

  • euri10 +

  • evangelineliu +

  • fengyqf +

  • fjdiod

  • fl4p +

  • fleimgruber +

  • gfyoung

  • h-vetinari

  • harisbal +

  • henriqueribeiro +

  • himanshu awasthi

  • hongshaoyang +

  • igorfassen +

  • jalazbe +

  • jbrockmendel

  • jh-wu +

  • justinchan23 +

  • louispotok

  • marcosrullan +

  • miker985

  • nicolab100 +

  • nprad

  • nsuresh +

  • ottiP

  • pajachiet +

  • raguiar2 +

  • ratijas +

  • realead +

  • robbuckley +

  • saurav2608 +

  • sideeye +

  • ssikdar1

  • svenharris +

  • syutbai +

  • testvinder +

  • thatneat

  • tmnhat2001

  • tomascassidy +

  • tomneep

  • topper-123

  • vkk800 +

  • winlu +

  • ym-pett +

  • yrhooke +

  • ywpark1 +

  • zertrin

  • zhezherun +