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 現在能夠儲存包含缺失值的整數 dtype。這個長期請求的功能透過使用擴充套件型別來實現。

注意

IntegerArray 目前仍處於實驗階段。其 API 或實現可能會在未經通知的情況下發生更改。

我們可以使用指定的 dtype 來構造一個 Series。dtype 字串 Int64 是一個 pandas ExtensionDtype。使用傳統的缺失值標記 np.nan 指定列表或陣列將推斷為整數 dtype。 Series 的顯示也將使用 NaN 來指示字串輸出中的缺失值。(GH 20700GH 20747GH 22441GH 21789GH 22346

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

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

對這些 dtype 的操作將像其他 pandas 操作一樣傳播 NaN

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

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

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

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

# coerce when needed
In [7]: s + 0.01
Out[7]: 
0    1.01
1    2.01
2    <NA>
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

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

這些 dtype 可以被合併、重塑和強制轉換。

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

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

諸如 sum 之類的歸約和分組操作有效。

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

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

警告

整數 NA 支援目前使用大寫 dtype 版本,例如 Int8 而不是傳統的 int8。這在未來可能會被更改。

有關更多資訊,請參閱可為空的整數資料型別

訪問 Series 或 Index 中的值#

已新增 Series.arrayIndex.array,用於提取 Series 或 Index 的底層陣列。(GH 19954GH 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]: 140469006801616

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

如果你需要一個實際的 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)。這可用於建立任何擴充套件陣列,包括由第三方庫註冊的擴充套件陣列。有關擴充套件陣列的更多資訊,請參閱資料型別文件

In [26]: pd.array([1, 2, pd.NA], 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, str): ['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 資料#

除了以前的 IntervalIndexPeriodIndex 之外,現在還可以在 SeriesDataFrame 中儲存 IntervalPeriod 資料(GH 19453GH 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]
dtype: interval

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

對於 Period

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
dtype: period[D]

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

以前,這些資料將被轉換為 object dtype 的 NumPy 陣列。總的來說,這應該會在將 interval 或 period 陣列儲存在 SeriesDataFrame 的列中時,帶來更好的效能。

使用 Series.arraySeries 中提取 interval 或 period 的底層陣列。

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 資料的新的擴充套件陣列。

警告

為了向後相容,Series.values 對於 Interval 和 Period 資料會繼續返回一個 NumPy 物件陣列。我們建議在需要 Series 中儲存的資料陣列時使用 Series.array,在確定需要 NumPy 陣列時使用 Series.to_numpy()

有關更多資訊,請參閱資料型別屬性和底層資料

與兩個 MultiIndex 進行連線#

現在可以使用 DataFrame.merge()DataFrame.join() 來連線具有重疊索引級別的 multi-indexed DataFrame 例項(GH 6360)。

請參閱合併、連線和串聯文件部分。

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

對於早期版本,可以使用以下方法實現。

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

函式 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]

新的 Styler.pipe() 方法#

Styler 類增加了一個 pipe() 方法。這提供了一種便捷的方式來應用使用者預定義的樣式函式,並且可以在筆記本中重複使用 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 0x7fc18ea3d050>

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

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

有關更多詳細資訊,請參閱重新命名的高階文件

其他增強功能#

向後不相容的 API 更改#

pandas 0.24.0 包含一系列 API 破壞性更改。

提高了依賴項的最低版本#

我們已更新了依賴項的最低支援版本(GH 21242GH 18742GH 23774GH 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 格式的儲存,而是將其替換為對 pyarrow 的引用(GH 21639GH 23053)。

對於 DataFrame.to_csvline_terminator,使用了 os.linesep#

DataFrame.to_csv() 現在使用 os.linesep() 而不是 '\n' 作為預設行終止符(GH 20353)。此更改僅影響 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,將 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#

read_excel()read_csv() 使用 Python 引擎時存在一個錯誤,即當 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 17697GH 11736GH 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[us, UTC+05:30]', freq=None)

解析具有不同 UTC 偏移量的日期時間字串現在將建立一個具有不同 UTC 偏移量的 datetime.datetime 物件索引。

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[us, 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_timeto_timestamp(how='end') 中的時間值(#

在呼叫 Series.dt.end_timePeriod.end_timePeriodIndex.end_time、使用 how='end' 呼叫 Period.to_timestamp() 或使用 how='end' 呼叫 PeriodIndex.to_timestamp() 時,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.999999')

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

帶時區感知資料的 Series.unique(#

對於帶時區的日期時間值,Series.unique() 的返回型別已從 numpy.ndarray(包含 Timestamp 物件)更改為 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[us, UTC]

稀疏資料結構重構(#

SparseArraySparseSeries 的底層陣列以及 SparseDataFrame 中的列)現在是一個擴充套件陣列(GH 21978GH 19056GH 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 傳遞標量。

  • 將稀疏和密集 Series 混合使用 concat() 的結果是一個帶有稀疏值的 Series,而不是 SparseSeries

  • SparseDataFrame.combineDataFrame.combine_first 不再支援將稀疏列與密集列合併同時保留稀疏子型別。結果將是一個 object-dtype 的 SparseArray。

  • 現在允許將 SparseArray.fill_value 設定為具有不同 dtype 的填充值。

  • 當對具有稀疏值的單個列進行切片時,DataFrame[column] 現在是一個帶有稀疏值的 Series,而不是 SparseSeriesGH 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,具體取決於所有列或僅部分列被虛擬編碼。現在,始終返回 DataFrameGH 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.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.DataFrame

In [70]: type(pd.get_dummies(df[['B', 'C']], sparse=True))
Out[70]: pandas.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

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/core/frame.py:2236, in DataFrame.to_dict(self, orient, into, index)
   2134 """
   2135 Convert the DataFrame to a dictionary.
   2136 
   (...)   2232  defaultdict(<class 'list'>, {'col1': 2, 'col2': 0.75})]
   2233 """
   2234 from pandas.core.methods.to_dict import to_dict
-> 2236 return to_dict(self, orient, into=into, index=index)

File ~/work/pandas/pandas/pandas/core/methods/to_dict.py:259, in to_dict(df, orient, into, index)
    257 elif orient == "index":
    258     if not df.index.is_unique:
--> 259         raise ValueError("DataFrame index must be unique for orient='index'.")
    260     columns = df.columns.tolist()
    261     if are_all_object_dtype_cols:

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

Tick DateOffset 規範化限制(#

不再支援使用 normalize=True 建立 Tick 物件(DayHourMinuteSecondMilliMicroNano)。這可以防止加法可能不單調或不關聯的意外行為。(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>

類似地,一個 Period 減去一個 PeriodIndex 現在將返回一個 DateOffset 物件索引,而不是一個 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')

從 DataFrame 加/減 NaN#

從具有 timedelta64[ns] 資料型別的 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

先前行為:

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)。

受影響的情況是:

  • 與具有 1 行或 1 列的二維 np.ndarray 進行操作,現在將以 np.ndarray 的方式進行廣播(GH 23000)。

  • 長度與 DataFrame 行數匹配的列表或元組現在將引發 ValueError,而不是逐列操作(GH 22880)。

  • 長度與 DataFrame 列數匹配的列表或元組現在將逐行操作,而不是引發 ValueErrorGH 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

先前行為:

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

In [88]: df + arr[[0], :]
Out[88]: 
   0  1
0  0  2
1  2  4
2  4  6
# 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

In [90]: df + (1, 2)
Out[90]: 
   0  1
0  1  3
1  3  5
2  5  7
# 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

先前行為:

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

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

Series 和 Index 資料型別不相容#

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

連線更改#

在包含 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
dtype: float64

日期時間類似 API 更改#

其他 API 更改#

  • 新構造的、具有整數 dtype 的空 DataFrame 現在只有在指定了 index 時才會被強制轉換為 float64GH 22858

  • Series.str.cat() 現在如果 others 是一個 set,則會引發錯誤(GH 23009

  • 將標量值傳遞給 DatetimeIndexTimedeltaIndex 現在將引發 TypeError 而不是 ValueErrorGH 23539

  • max_rowsmax_cols 引數已從 HTMLFormatter 中移除,因為截斷由 DataFrameFormatter 處理(GH 23818

  • read_csv() 現在如果具有缺失值的列被宣告為 bool 型別,則會引發 ValueErrorGH 20591

  • MultiIndex.to_frame() 產生的 DataFrame 的列順序現在保證與 MultiIndex.names 順序匹配。(GH 22420

  • DatetimeIndex 錯誤地傳遞給 MultiIndex.from_tuples(),而不是元組序列,現在將引發 TypeError 而不是 ValueErrorGH 24024

  • pd.offsets.generate_range() 的引數 time_rule 已被移除;請使用 offset 代替(GH 24157

  • 在 0.23.x 中,pandas 會在合併數值列(例如 int 型別列)和 object 型別列時引發 ValueErrorGH 9780)。我們已重新啟用合併 object 和其他資料型別的能力;pandas 仍然會在合併由僅包含字串組成的數值型別和 object 型別列時引發錯誤(GH 21681

  • 使用重複名稱訪問 MultiIndex 的級別(例如在 get_level_values() 中)現在將引發 ValueError 而不是 KeyErrorGH 21678)。

  • 如果子型別無效,無效構造 IntervalDtype 現在將始終引發 TypeError 而不是 ValueErrorGH 21185

  • 嘗試使用非唯一 MultiIndex 對 DataFrame 進行重新索引現在將引發 ValueError 而不是 ExceptionGH 21770

  • Index 減法將嘗試逐元素操作,而不是引發 TypeErrorGH 19369

  • pandas.io.formats.style.Styler 在使用 to_excel() 時支援 number-format 屬性(GH 22015

  • DataFrame.corr()Series.corr() 現在在提供無效方法時會引發帶有有用錯誤訊息的 ValueError,而不是 KeyErrorGH 22298

  • shift() 現在將始終返回副本,而不是像以前那樣在偏移 0 時返回自身(GH 22397

  • DataFrame.set_index() 現在會產生更好的(且不那麼頻繁的)KeyError,對錯誤型別會引發 ValueError,並且在 drop=True 時不會因重複的列名而失敗。(GH 22484

  • 用多個相同型別的 ExtensionArray 對 DataFrame 的單行進行切片現在將保留 dtype,而不是強制轉換為 object(GH 22784

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

  • Series.searchsorted() 接收一個標量值進行搜尋時,現在返回一個標量而不是陣列(GH 23801)。

  • Categorical.searchsorted() 接收一個標量值進行搜尋時,現在返回一個標量而不是陣列(GH 23466)。

  • Categorical.searchsorted() 現在如果搜尋的鍵在類別中未找到,則引發 KeyError 而不是 ValueErrorGH 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 將引發 ValueErrorGH 24753

擴充套件型別更改#

相等性和可雜湊性

pandas 現在要求擴充套件 dtype 是可雜湊的(即相應的 ExtensionDtype 物件;ExtensionArray 的值不是必需的)。基類實現了預設的 __eq____hash__。如果您有一個引數化的 dtype,您應該更新 ExtensionDtype._metadata 元組以匹配您的 __init__ 方法的簽名。有關更多資訊,請參閱 pandas.api.extensions.ExtensionDtypeGH 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 運算子支援 文件部分。

Other changes

Bug 修復

  • 使用 ExtensionArray 和整數索引的 SeriesSeries.get() 中的錯誤(GH 21257

  • Series.shift() 現在分派到 ExtensionArray.shift()GH 22386

  • Series.combine()Series 內的 ExtensionArray 上可以正確工作(GH 20825

  • 帶有標量引數的 Series.combine() 現在適用於任何函式型別(GH 21248

  • Series.astype()DataFrame.astype() 現在分派到 ExtensionArray.astype()GH 21185)。

  • 用多個相同型別的 ExtensionArray 對 DataFrame 的單行進行切片現在將保留 dtype,而不是強制轉換為 object(GH 22784

  • 連線具有不同擴充套件 dtype 的多個 Series 時,未強制轉換為 object dtype 的錯誤(GH 22994

  • ExtensionArray 支援的 Series 現在可以與 util.hash_pandas_object() 一起使用(GH 23066

  • DataFrame.stack() 對於每列具有相同擴充套件 dtype 的 DataFrame 不再轉換為 object dtype。輸出 Series 將具有與列相同的 dtype(GH 23077)。

  • Series.unstack()DataFrame.unstack() 不再將擴充套件陣列轉換為 object-dtype ndarrays。輸出 DataFrame 中的每個列現在將具有與輸入相同的 dtype (GH 23077)。

  • 在對 Dataframe.groupby() 進行分組並對 ExtensionArray 進行聚合時,沒有返回實際的 ExtensionArray dtype 的錯誤 (GH 23227)。

  • pandas.merge() 中,當基於擴充套件陣列列進行合併時出現的錯誤 (GH 23020)。

棄用#

  • MultiIndex.labels 已被棄用,並被 MultiIndex.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 引數時,時區轉換一個帶時區的 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)。

  • Series.where() 中使用 Categorical 資料時,提供一個不在類別中的 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)。

  • 將沒有精度的 dtype(如 np.dtype('datetime64')timedelta64)傳遞給 IndexDatetimeIndexTimedeltaIndex 已被棄用。請使用納秒精度 dtype (GH 24753)。

整數加/減與日期時間和時間差的運算已棄用#

過去,使用者在某些情況下可以對 TimestampDatetimeIndexTimedeltaIndex 進行整數或整數 dtype 陣列的加減運算。

此用法現已棄用。請改用新增或減去物件 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 在接收整數資料和時區時的行為將發生改變。以前,這些將被解釋為所需時區中的實際時間。未來,這些將被解釋為 UTC 中的實際時間,然後轉換為所需時區 (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 陣列#

從具有帶時區日期時間資料的 SeriesIndex 轉換為 NumPy 陣列的預設行為將改為保留時區 (GH 23569)。

NumPy 沒有專門的時區感知日期時間 dtype。過去,將具有時區感知日期的 SeriesDatetimeIndex 轉換為 NumPy 陣列,是透過

  1. 將帶時區的資料轉換為 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
dtype: datetime64[us, 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]')

以上所有內容也適用於具有帶時區值的 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 方法現在如果將不帶單位的時間戳 dtype(例如 np.datetime64)傳遞給 dtype 引數,將引發 ValueError (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 引數重新命名為 valueGH 14645

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

  • Index.searchsorted()key 引數重新命名為 valueGH 14645

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

  • 移除了之前已棄用的模組 pandas.jsonGH 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 引數重新命名為 errorsGH 14967

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

效能改進#

Bug 修復#

分類#

  • 修復了 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)。

  • 在更改 dtype 強制轉換後,使用空值和布林類別構造 CategoricalIndex 時會引發 ValueError 的錯誤(GH 22702)。

  • 修復了 Categorical.take() 中使用者提供的 fill_value 未被編碼的錯誤,這可能導致 ValueError、結果不正確或段錯誤(GH 23296)。

  • Series.unstack() 中,指定一個不在類別中的 fill_value 現在會引發 TypeError,而不是忽略 fill_valueGH 23284)。

  • 在對分類資料進行 DataFrame.resample() 並聚合時,分類 dtype 丟失的錯誤(GH 23227)。

  • 修復了 .str 訪問器在呼叫 CategoricalIndex.str 建構函式時總是失敗的錯誤(GH 23555, GH 23556)。

  • 修復了 Series.where() 導致分類資料丟失分類 dtype 的錯誤(GH 24077)。

  • 修復了 Categorical.apply()NaN 值可能被處理不確定的錯誤。現在它們保持不變(GH 24241)。

  • 修復了 Categorical 比較方法在與 DataFrame 操作時錯誤地引發 ValueError 的錯誤(GH 24630)。

  • 修復了使用 rename=True 設定更少新類別時,Categorical.set_categories() 導致段錯誤的錯誤(GH 24675)。

日期時間型別#

  • 修復了兩個具有不同 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)。

  • 修復了 DatetimeIndextimedelta64[ns] dtype 陣列進行比較時,在某些情況下錯誤地引發 TypeError,而在另一些情況下又未能引發錯誤(GH 22074)。

  • 修復了 DatetimeIndex 與 object-dtyped 陣列進行比較時的錯誤(GH 22074)。

  • 修復了具有 datetime64[ns] dtype 的 DataFrame 與 Timedelta 類物件進行加減法操作的錯誤(GH 22005, GH 22163)。

  • 修復了具有 datetime64[ns] dtype 的 DataFrameDateOffset 物件進行加減法操作時,返回 object dtype 而非 datetime64[ns] dtype 的錯誤(GH 21610, GH 22163)。

  • 修復了具有 datetime64[ns] dtype 的 DataFrameNaT 進行比較時出現錯誤的錯誤(GH 22242, GH 22163)。

  • 修復了具有 datetime64[ns] dtype 的 DataFrame 減去 Timestamp 類物件時,錯誤地返回 datetime64[ns] dtype 而非 timedelta64[ns] dtype 的錯誤(GH 8554, GH 22163)。

  • 修復了具有 datetime64[ns] dtype 的 DataFrame 減去具有非納秒單位的 np.datetime64 物件時,未能轉換為納秒的錯誤(GH 18874, GH 22163)。

  • 修復了 DataFrame 與 Timestamp 類物件進行比較時,對於不匹配型別的不等比較,未能引發 TypeError 的錯誤(GH 8932, GH 22163)。

  • 修復了包含 datetime64[ns] 的混合 dtype 的 DataFrame 在相等比較時錯誤地引發 TypeError 的錯誤(GH 13128, GH 22163)。

  • 修復了當單列 DataFrame 包含時區感知的 datetime 值時,DataFrame.values 返回 DatetimeIndex 的錯誤。現在返回一個 Timestamp 物件組成的二維 numpy.ndarrayGH 24024)。

  • 修復了 DataFrame.eq()NaT 比較時,錯誤地返回 TrueNaN 的錯誤(GH 15697, GH 22163)。

  • 修復了 DatetimeIndex 減法錯誤地未能引發 OverflowError 的錯誤(GH 22492, GH 22508)。

  • 修復了 DatetimeIndex 錯誤地允許使用 Timedelta 物件進行索引的錯誤(GH 20464)。

  • 修復了 DatetimeIndex 中,當原始頻率為 None 時,頻率被設定的錯誤(GH 22150)。

  • 修復了 DatetimeIndexround(), ceil(), floor())和 Timestampround(), ceil(), floor())的舍入方法的錯誤,這些錯誤可能導致精度損失(GH 22591)。

  • 修復了 to_datetime() 使用 Index 引數時會從結果中丟棄 name 的錯誤(GH 21697)。

  • 修復了 PeriodIndex 中,新增或減去 timedeltaTick 物件會產生不正確結果的錯誤(GH 22988)。

  • 修復了具有 period-dtype 資料的 Series repr 中資料前缺少空格的錯誤(GH 23601)。

  • 修復了 date_range() 中,當使用負頻率遞減開始日期到過去結束日期時的錯誤(GH 23270)。

  • 修復了當在 NaT 序列上呼叫 Series.min() 時,返回 NaN 而不是 NaT 的錯誤(GH 23282)。

  • 修復了 Series.combine_first() 未能正確對齊分類資料,導致 self 中的缺失值未被 other 中的有效值填充的錯誤(GH 24147)。

  • 修復了 DataFrame.combine() 在處理 datetimelike 值時引發 TypeError 的錯誤(GH 23079)。

  • 修復了 date_range() 在頻率為 Day 或更高時,足夠遠的未來日期可能會迴繞到過去,而不是引發 OutOfBoundsDatetime 的錯誤(GH 14187)。

  • bug in period_range() to_datetime函式忽略了當start和end提供為Period物件時它們的頻率(GH 20535)。

  • bug in PeriodIndex when its freq.n屬性大於1,此時新增一個DateOffset物件會返回錯誤的結果(GH 23215

  • bug in Series when setting datetimelike values,它會將字串索引解釋為字元列表(GH 23451

  • bug in DataFrame when creating a new column from an ndarray of timezone-aware Timestamp objects, it created an object-dtype column instead of a datetime with timezone column(GH 23932

  • bug in Timestamp constructor that would drop the frequency of an input TimestampGH 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 ValueErrorGH 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 ValueErrorGH 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 ValueErrorGH 24569

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

時間差#

  • 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 timedelta64GH 22390

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

  • fixed bug where subtracting Timedelta from an object-dtyped array would raise TypeErrorGH 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 TypeErrorGH 22696

  • bug in TimedeltaIndex where adding a timezone-aware datetime scalar incorrectly returned a timezone-naive DatetimeIndexGH 23215

  • bug in TimedeltaIndex where adding np.timedelta64('NaT') incorrectly returned an all-NaT DatetimeIndex instead of an all-NaT TimedeltaIndexGH 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 Float64IndexGH 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 TypeErrorGH 24710

時區#

偏移量#

  • FY5253 中存在一個 bug,日期偏移量在算術運算中可能錯誤地引發 AssertionError (GH 14774)

  • DateOffset 中存在一個 bug,關鍵字引數 weekmilliseconds 被接受但被忽略。現在傳入這些引數將引發 ValueError (GH 19398)

  • DateOffsetDataFramePeriodIndex 相加時存在一個 bug,錯誤地引發了 TypeError (GH 23215)

  • DateOffset 物件與非 DateOffset 物件(特別是字串)進行比較時存在一個 bug,錯誤地引發 ValueError,而不是在相等性檢查時返回 False,在不等性檢查時返回 True (GH 23524)

數值#

  • Series__rmatmul__ 中存在一個 bug,不支援矩陣向量乘法 (GH 21530)

  • factorize() 中存在一個 bug,當輸入是隻讀陣列時會失敗 (GH 12813)

  • 修復了 unique() 函式處理帶符號零不一致的問題:對於某些輸入 0.0 和 -0.0 被視為相等,對於某些輸入則不相等。現在它們對於所有輸入都被視為相等 (GH 21866)

  • DataFrame.agg()DataFrame.transform()DataFrame.apply() 中存在一個 bug,當傳入函式列表和 axis=1 時(例如 df.apply(['sum', 'mean'], axis=1)),會錯誤地引發 TypeError。對於所有這三個方法,此類計算現在都能正確完成。(GH 16679)。

  • Series 與日期時間標量和陣列的比較中存在一個 bug (GH 22074)

  • DataFrame 的布林型別和整數型別之間進行乘法運算時存在一個 bug,返回 object 型別而不是整數型別 (GH 22047, GH 22163)

  • DataFrame.apply() 中存在一個 bug,當傳入字串引數和額外的 positional 或 keyword 引數時(例如 df.apply('sum', min_count=1)),會錯誤地引發 TypeError (GH 22376)

  • DataFrame.astype() 轉換為擴充套件 dtype 時可能引發 AttributeError (GH 22578)

  • DataFrame 中,timedelta64[ns] 型別的算術運算與整數型別的 ndarray 運算存在一個 bug,錯誤地將 ndarray 當作 timedelta64[ns] 型別處理 (GH 23114)

  • Series.rpow() 中存在一個 bug,當輸入為 object 型別的 NaN 時,對於 1 ** NA,返回 NaN 而不是 1 (GH 22922)。

  • Series.agg() 現在可以處理 numpy 的 NaN 感知方法,例如 numpy.nansum() (GH 19629)

  • Series.rank()DataFrame.rank() 中存在一個 bug,當 pct=True 且行數超過 224 時,百分比會大於 1.0 (GH 18271)

  • 諸如 DataFrame.round() 這種使用非唯一 CategoricalIndex() 的呼叫現在能返回預期的資料。之前,資料會被不正確地複製 (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)。

轉換#

字串#

  • Index.str.partition() 中存在一個 bug,它不是 NaN 安全的 (GH 23558)。

  • Index.str.split() 中存在一個 bug,它不是 NaN 安全的 (GH 23677)。

  • Series.str.contains() 中存在一個 bug,它沒有遵守 Categorical 型別的 Seriesna 引數 (GH 22158)

  • Index.str.cat() 中存在一個 bug,當結果只包含 NaN 時 (GH 24044)

Interval#

  • IntervalIndex 建構函式中存在一個 bug,其中 closed 引數未始終覆蓋推斷出的 closed (GH 19370)

  • IntervalIndex 的 repr 中存在一個 bug,缺少了間隔列表後的尾隨逗號 (GH 20611)

  • Interval 中存在一個 bug,標量算術運算未保留 closed 值 (GH 22313)

  • IntervalIndex 中存在一個 bug,使用日期時間類值進行索引時會引發 KeyError (GH 20636)

  • IntervalTree 中存在一個 bug,包含 NaN 的資料會觸發警告,並導致使用 IntervalIndex 的索引查詢不正確 (GH 23352)

索引#

  • DataFrame.ne() 中存在一個 bug,如果列包含名為 “dtype” 的列名,則會失敗 (GH 22383)

  • 當透過 .loc 請求單個缺失標籤時,KeyError 的堆疊跟蹤現在更短、更清晰 (GH 21557)

  • PeriodIndex 現在在查詢格式錯誤的字串時會發出 KeyError,這與 DatetimeIndex 的行為一致 (GH 22803)

  • .ix 在第一層是整數型別的 MultiIndex 中查詢缺失的整數標籤時,它現在會引發 KeyError,這與平坦的 Int64Index 的情況一致,而不是回退到位置索引 (GH 21593)

  • Index.reindex() 中存在一個 bug,當對 tz-naive 和 tz-aware 的 DatetimeIndex 進行重索引時 (GH 8306)

  • Series.reindex() 中存在一個 bug,當對空 Series 使用 datetime64[ns, tz] 型別進行重索引時 (GH 20869)

  • DataFrame 中存在一個 bug,當使用 .loc 和帶時區資訊的 DatetimeIndex 設定值時 (GH 11365)

  • DataFrame.__getitem__ 現在接受字典和字典鍵作為類列表標籤,與 Series.__getitem__ 一致 (GH 21294)

  • 修復了 DataFrame[np.nan] 在列不唯一時的情況 (GH 21428)

  • DatetimeIndex 中存在一個 bug,當使用納秒解析度日期和時區進行索引時 (GH 11679)

  • 存在一個 bug,使用包含負值的 Numpy 陣列進行索引時會修改索引器 (GH 21867)

  • 存在一個 bug,混合索引不允許在 .at 中使用整數 (GH 19860)

  • Float64Index.get_loc 現在在傳遞布林鍵時引發 KeyError。(GH 19087

  • DataFrame.loc() 中存在一個 bug,當使用 IntervalIndex 進行索引時 (GH 19977)

  • Index 不再篡改 NoneNaNNaT,即它們被視為三個不同的鍵。但是,對於數值 Index,這三者仍然會被強制轉換為 NaN (GH 22332)

  • scalar in Index 中存在一個 bug,如果標量是浮點數而 Index 是整數型別 (GH 22085)

  • MultiIndex.set_levels() 中存在一個 bug,當 level 的值不可訂閱時 (GH 23273)

  • 存在一個 bug,透過 Index 設定 timedelta 列會導致其被強制轉換為 double,從而丟失精度 (GH 23511)

  • Index.union()Index.intersection() 中存在一個 bug,對於某些情況,結果 Index 的名稱未正確計算 (GH 9943, GH 9862)

  • Index 使用布林 Index 進行切片時存在一個 bug,可能會引發 TypeError (GH 22533)

  • PeriodArray.__setitem__ 中存在一個 bug,當接受切片和類列表值時 (GH 23978)

  • DatetimeIndexTimedeltaIndex 中存在一個 bug,當使用 Ellipsis 進行索引時會丟失其 freq 屬性 (GH 21282)

  • iat 中存在一個 bug,使用它來分配不相容的值會建立一個新列 (GH 23236)

Missing#

  • DataFrame.fillna() 中存在一個 bug,當一列包含 datetime64[ns, tz] 型別時會引發 ValueError (GH 15522)

  • Series.hasnans() 中存在一個 bug,它可能被錯誤地快取,並且在引入 null 元素後返回不正確的結果 (GH 19700)

  • Series.isin() 現在將所有 NaN 浮點數視為相等,包括對於 np.object_ 型別。此行為與 float64 的行為一致 (GH 22119)

  • unique() 不再篡改 np.object_ 型別的 NaN 浮點數和 NaT 物件,即 NaT 不再被強制轉換為 NaN 值,而是被視為一個不同的實體。(GH 22295

  • DataFrameSeries 現在可以正確處理帶有硬掩碼的 numpy 掩碼陣列。之前,從帶有硬掩碼的掩碼陣列構建 DataFrame 或 Series 會建立包含底層值的 pandas 物件,而不是預期的 NaN。(GH 24574

  • DataFrame 建構函式中存在一個 bug,當處理 numpy 掩碼記錄陣列時,dtype 引數未被遵守。(GH 24874

MultiIndex#

IO#

  • read_csv() 中存在一個錯誤,即當使用布林類別 CategoricalDtype 指定列時,該列無法從字串正確轉換為布林值(GH 20498)。

  • read_csv() 中存在一個錯誤,即在 Python 2.x 中,Unicode 列名無法被正確識別(GH 13253)。

  • DataFrame.to_sql() 在寫入時區感知資料(datetime64[ns, tz] dtype)時會引發 TypeError 的錯誤(GH 9086)。

  • DataFrame.to_sql() 中存在一個錯誤,即在支援的資料庫(例如 PostgreSQL)中,一個樸素的 DatetimeIndex 會被寫入為 TIMESTAMP WITH TIMEZONE 型別(GH 23510)。

  • read_excel() 在指定了空的 parse_cols 引數時存在錯誤(GH 9208)。

  • read_html() 在考慮 skiprowsheader 引數時,不再忽略 <thead> 中全為空格的 <tr>。以前,使用者需要減小 headerskiprows 的值來繞過這個問題。(GH 21641)。

  • read_excel() 將正確顯示之前已棄用的 sheetname 引數的棄用警告(GH 17994)。

  • read_csv()read_table() 將會丟擲 UnicodeError 而不是崩潰,以處理編碼錯誤的字串(GH 22748)。

  • read_csv() 將正確解析時區感知日期時間(GH 22256)。

  • read_csv() 中存在一個錯誤,當資料分塊讀取時,C 引擎對記憶體管理進行了過早的最佳化(GH 23509)。

  • read_csv() 中存在一個錯誤,在提取多重索引時,未命名的列被錯誤地識別(GH 23687)。

  • read_sas() 將正確解析寬度小於 8 位元組的 sas7bdat 檔案中的數字(GH 21616)。

  • read_sas() 將正確解析包含大量列的 sas7bdat 檔案(GH 22628)。

  • read_sas() 將正確解析資料頁型別(page type)的第 7 位(bit 7)被設定(因此頁型別為 128 + 256 = 384)的 sas7bdat 檔案(GH 16615)。

  • read_sas() 中存在一個錯誤,即在檔案格式無效時會引發錯誤的異常(GH 24548)。

  • detect_client_encoding() 中存在一個錯誤,當在 mod_wsgi 程序中匯入時,由於 stdout 訪問受限,可能發生的 IOError 未被處理(GH 21552)。

  • DataFrame.to_html() 在 `index=False` 時,截斷的 DataFrame 會丟失截斷指示符 (...)(GH 15019GH 22783)。

  • DataFrame.to_html() 在 `index=False` 且行索引和列索引都是 MultiIndex 時存在錯誤(GH 22579)。

  • DataFrame.to_html() 在 `index_names=False` 時,會顯示索引名稱的錯誤(GH 22747)。

  • DataFrame.to_html() 在 `header=False` 時,不顯示行索引名稱的錯誤(GH 23788)。

  • DataFrame.to_html() 在 `sparsify=False` 時存在一個錯誤,導致引發 TypeErrorGH 22887)。

  • DataFrame.to_string() 中存在一個錯誤,當 `index=False` 且第一列的值寬度大於第一列的標題寬度時,列對齊會出錯(GH 16839GH 13032)。

  • DataFrame.to_string() 中存在一個錯誤,導致 DataFrame 的表示形式不能填滿整個視窗(GH 22984)。

  • DataFrame.to_csv() 中存在一個錯誤,即當單級 MultiIndex 被錯誤地寫入為元組時。現在只寫入索引的值(GH 19589)。

  • 當 `format` 引數被傳遞給建構函式時,HDFStore 將引發 ValueErrorGH 13291)。

  • HDFStore.append() 在追加一個包含空字串列且 `min_itemsize` < 8 的 DataFrame 時存在錯誤(GH 12242)。

  • read_csv() 的 C 引擎在解析 NaN 值時存在記憶體洩漏,這是由於在完成或錯誤時清理不足(GH 21353)。

  • read_csv() 中存在一個錯誤,當 `skipfooter` 與 `nrows`、`iterator` 或 `chunksize` 一起傳遞時,會引發不正確的錯誤訊息(GH 23711)。

  • read_csv() 中存在一個錯誤,當 MultiIndex 索引名稱未提供時,會對其進行不當處理(GH 23484)。

  • read_csv() 中存在一個錯誤,當方言的值與預設引數衝突時,會引發不必要的警告(GH 23761)。

  • read_html() 中存在一個錯誤,當提供無效的 `flavor` 時,錯誤訊息沒有顯示有效的 `flavor` 選項(GH 23549)。

  • read_excel() 中存在一個錯誤,即使沒有指定標題,也會提取額外的標題名稱(GH 11733)。

  • read_excel() 中存在一個錯誤,在 Python 2.x 中,列名有時無法正確轉換為字串(GH 23874)。

  • read_excel() 中存在一個錯誤,即 index_col=None 未被遵守,仍然解析索引列(GH 18792GH 20480)。

  • read_excel() 中存在一個錯誤,即當 `usecols` 作為字串傳遞時,沒有對正確的列名進行驗證(GH 20480)。

  • DataFrame.to_dict() 在結果字典包含非 Python 標量(numeric data 的情況下)時存在錯誤(GH 23753)。

  • DataFrame.to_string(), DataFrame.to_html(), DataFrame.to_latex() 在 `float_format` 引數傳遞字串時,將正確格式化輸出(GH 21625, GH 22270)。

  • read_csv() 中存在一個錯誤,當嘗試將 'inf' 用作整數索引列的 `na_value` 時,會引發 OverflowErrorGH 17128)。

  • read_csv() 中存在一個錯誤,導致 Python 3.6+ 在 Windows 上的 C 引擎無法正確讀取帶有重音或特殊字元的 CSV 檔名(GH 15086)。

  • read_fwf() 中存在一個錯誤,即檔案的壓縮型別未能正確推斷(GH 22199)。

  • pandas.io.json.json_normalize() 中存在一個錯誤,當 `record_path` 的兩個連續元素是字典時,會引發 TypeErrorGH 22706)。

  • DataFrame.to_stata(), pandas.io.stata.StataWriterpandas.io.stata.StataWriter117 中存在一個錯誤,即異常發生時會留下一個部分寫入且無效的 dta 檔案(GH 23573)。

  • DataFrame.to_stata()pandas.io.stata.StataWriter117 中存在一個錯誤,即在使用帶非 ASCII 字元的 strLs 時會生成無效檔案(GH 23573)。

  • HDFStore 中存在一個錯誤,導致在 Python 3 中讀取在 Python 2 中用固定格式寫入的 DataFrame 時引發 ValueErrorGH 24510)。

  • DataFrame.to_string() 和更通用的浮點數 `repr` 格式化器中存在一個錯誤。當列中存在 `inf` 時,零不會被截斷,而 NA 值則會。現在,零會像 NA 值一樣被截斷(GH 24861)。

  • 截斷列數並存在一個寬的最後一列時,`repr` 中存在一個錯誤(GH 24849)。

繪圖#

  • DataFrame.plot.scatter()DataFrame.plot.hexbin() 中存在一個錯誤,當 IPython 的內聯後端顯示 colorbar 時,x 軸標籤和刻度標籤會消失(GH 10611GH 10678,以及 GH 20455)。

  • 使用 matplotlib.axes.Axes.scatter() 繪製具有 datetime 型別的 Series 時存在錯誤(GH 22039)。

  • DataFrame.plot.bar() 中存在一個錯誤,導致條形圖使用了多種顏色而不是單一顏色(GH 20585)。

  • 顏色引數驗證中的一個錯誤導致多餘的顏色被附加到給定的顏色陣列中。這影響了多個使用 matplotlib 的繪圖函式。(GH 20726)。

GroupBy/resample/rolling

  • Rolling.min()Rolling.max() 在 `closed='left'`、datetime 型別的索引以及 Series 中只有一個條目時存在錯誤,導致段錯誤(segfault)(GH 24718)。

  • GroupBy.first()GroupBy.last() 在 `as_index=False` 時存在錯誤,導致時區資訊丟失(GH 15884)。

  • 在跨越 DST 邊界進行下采樣時,DateFrame.resample() 存在錯誤(GH 8531)。

  • 當 n > 1 時,使用 `Day` 偏移量對 DateFrame.resample() 進行日期錨定存在錯誤(GH 24127)。

  • 當分組變數僅包含 NaN 且 numpy 版本 < 1.13 時,呼叫 SeriesGroupBy.count() 方法時,錯誤地引發了 ValueErrorGH 21956)。

  • 在 `closed='left'` 和 datetime 型別的索引下,Rolling.min() 存在多個錯誤,導致結果不正確甚至段錯誤(segfault)(GH 21704)。

  • Resampler.apply() 在嚮應用函式傳遞位置引數時存在錯誤(GH 14615)。

  • Series.resample() 在將 numpy.timedelta64 傳遞給 `loffset` 引數時存在錯誤(GH 7687)。

  • Resampler.asfreq() 在 `TimedeltaIndex` 的頻率是新頻率的子週期時存在錯誤(GH 13022)。

  • SeriesGroupBy.mean() 在值是整數但無法裝入 int64,導致溢位時存在錯誤(GH 22487)。

  • RollingGroupby.agg()ExpandingGroupby.agg() 現在支援將多個聚合函式作為引數(GH 15072)。

  • DataFrame.resample()Series.resample() 在按周偏移量(`'W'`)重取樣跨越 DST 轉換時存在錯誤(GH 9119GH 21459)。

  • DataFrame.expanding() 在聚合期間,`axis` 引數未被遵守(GH 23372)。

  • GroupBy.transform() 中存在一個錯誤,當輸入函式可以接受 DataFrame 但將其重新命名時,會導致丟失值(GH 23455)。

  • GroupBy.nth() 中存在一個錯誤,即列順序不總是被保留(GH 20760)。

  • GroupBy.rank() 在 `method='dense'` 和 `pct=True` 時,當一個組只有一個成員時,會引發 ZeroDivisionErrorGH 23666)。

  • 當呼叫 GroupBy.rank() 時,空組和 `pct=True` 會引發 ZeroDivisionErrorGH 22519)。

  • DataFrame.resample() 在對 TimeDeltaIndex 中的 NaT 進行重取樣時存在錯誤(GH 13223)。

  • DataFrame.groupby() 在選擇列時,沒有遵守 `observed` 引數,而是始終使用 `observed=False`(GH 23970)。

  • SeriesGroupBy.pct_change()DataFrameGroupBy.pct_change() 在計算百分比變化時,以前會在組間進行計算,現在會正確地按組進行計算(GH 21200GH 21235)。

  • 當擁有大量行(2^32)時,阻止建立雜湊表(GH 22805)。

  • 當對分類變數進行分組時,如果 `observed=True` 且分類列中存在 `nan`,則會引發 ValueError 並導致分組不正確(GH 24740GH 21151)。

Reshaping#

Sparse#

  • 將布林值、日期時間或時間差列更新為 Sparse 現在可行 (GH 22367)

  • 當 Series 已包含稀疏資料時,Series.to_sparse() 中的錯誤導致未正確構造 (GH 22389)

  • 為 SparseArray 建構函式提供 sparse_index 時,不再為所有 dtypes 預設將 na-value 設定為 np.nan。現在使用了 data.dtype 的正確 na_value。

  • SparseArray.nbytes 中的錯誤,由於未包含稀疏索引的大小而低報了其記憶體使用量。

  • 對於非 NA fill_valueSeries.shift() 的效能得到改善,因為值不再轉換為密集陣列。

  • 當按稀疏列分組時,對於非 NA fill_valueDataFrame.groupby 中的錯誤未將 fill_value 包含在組中 (GH 5078)

  • 在布林值 SparseSeries 上使用一元求反運算子 (~) 時出現錯誤。其效能也得到了改善 (GH 22835)

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

  • SparseArray.nonzero()SparseDataFrame.dropna() 中返回了移位/不正確的結果 (GH 21172)

  • 當 dtypes 丟失稀疏性時,DataFrame.apply() 中的錯誤 (GH 23744)

  • 當連線具有全稀疏值的 Series 列表時,concat() 中的錯誤會更改 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 上構建 pandas 現在最小目標為 macOS 10.9(如果執行在 macOS 10.9 或更高版本上)(GH 23424)

其他#

  • C 變數被宣告為外部連結,這會在其他 C 庫在 pandas 之前匯入時導致匯入錯誤。

貢獻者#

本次釋出共有 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 +