目录

搜索

输入搜索字词或模块,类或函数名称。

Essential Basic Functionality

在这里我们讨论了很多与pandas数据结构通用的基本功能。下面是如何创建一些在上一节中的示例中使用的对象:

In [1]: index = pd.date_range('1/1/2000', periods=8)

In [2]: s = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])

In [3]: df = pd.DataFrame(np.random.randn(8, 3), index=index,
   ...:                   columns=['A', 'B', 'C'])
   ...: 

In [4]: wp = pd.Panel(np.random.randn(2, 5, 4), items=['Item1', 'Item2'],
   ...:               major_axis=pd.date_range('1/1/2000', periods=5),
   ...:               minor_axis=['A', 'B', 'C', 'D'])
   ...: 

Head and Tail

要查看Series或DataFrame对象的小样本,请使用head()tail()方法。要显示的元素的默认数量为5,但您可以传递自定义数字。

In [5]: long_series = pd.Series(np.random.randn(1000))

In [6]: long_series.head()
Out[6]: 
0   -0.305384
1   -0.479195
2    0.095031
3   -0.270099
4   -0.707140
dtype: float64

In [7]: long_series.tail(3)
Out[7]: 
997    0.588446
998    0.026465
999   -1.728222
dtype: float64

Attributes and the raw ndarray(s)

pandas对象有一些属性,使您可以访问元数据

  • shape:给出对象的轴尺寸,与ndarray一致
  • 轴标签
    • Seriesindex(仅轴)
    • DataFrameindex(行)和columns
    • 面板itemsmajor_axisminor_axis

注意,这些属性可以安全地分配给

In [8]: df[:2]
Out[8]: 
                   A         B         C
2000-01-01  0.187483 -1.933946  0.377312
2000-01-02  0.734122  2.141616 -0.011225

In [9]: df.columns = [x.lower() for x in df.columns]

In [10]: df
Out[10]: 
                   a         b         c
2000-01-01  0.187483 -1.933946  0.377312
2000-01-02  0.734122  2.141616 -0.011225
2000-01-03  0.048869 -1.360687 -0.479010
2000-01-04 -0.859661 -0.231595 -0.527750
2000-01-05 -1.296337  0.150680  0.123836
2000-01-06  0.571764  1.555563 -0.823761
2000-01-07  0.535420 -1.032853  1.469725
2000-01-08  1.304124  1.449735  0.203109

要获取数据结构中的实际数据,只需访问属性:

In [11]: s.values
Out[11]: array([ 0.1122,  0.8717, -0.8161, -0.7849,  1.0307])

In [12]: df.values
Out[12]: 
array([[ 0.1875, -1.9339,  0.3773],
       [ 0.7341,  2.1416, -0.0112],
       [ 0.0489, -1.3607, -0.479 ],
       [-0.8597, -0.2316, -0.5278],
       [-1.2963,  0.1507,  0.1238],
       [ 0.5718,  1.5556, -0.8238],
       [ 0.5354, -1.0329,  1.4697],
       [ 1.3041,  1.4497,  0.2031]])

In [13]: wp.values
Out[13]: 
array([[[-1.032 ,  0.9698, -0.9627,  1.3821],
        [-0.9388,  0.6691, -0.4336, -0.2736],
        [ 0.6804, -0.3084, -0.2761, -1.8212],
        [-1.9936, -1.9274, -2.0279,  1.625 ],
        [ 0.5511,  3.0593,  0.4553, -0.0307]],

       [[ 0.9357,  1.0612, -2.1079,  0.1999],
        [ 0.3236, -0.6416, -0.5875,  0.0539],
        [ 0.1949, -0.382 ,  0.3186,  2.0891],
        [-0.7283, -0.0903, -0.7482,  1.3189],
        [-2.0298,  0.7927,  0.461 , -0.5427]]])

如果DataFrame或Panel包含同质类型数据,则ndarray实际上可以就地修改,并且更改将反映在数据结构中。对于异构数据(例如,某些DataFrame的列不是全部相同的dtype),情况就不是这样。与轴标签不同,值属性本身不能分配给。

注意

当使用元素原始数据中不单独存在数值类型时,将选择所得到的ndarray的dtype以适应所有涉及的数据。例如,如果涉及字符串,结果将是对象dtype。如果只有浮点数和整数,结果数组将是float dtype。

Accelerated operations

pandas支持使用numexpr库(从0.11.0开始)和bottleneck库加速某些类型的二进制数值和布尔运算。

这些库在处理大型数据集时非常有用,并提供大的加速。numexpr使用智能分块,缓存和多个内核。bottleneck是一组专门的cython例程,当处理具有nans的数组时,它们特别快。

以下是一个示例(使用100列x 100,000行DataFrames):

操作 0.11.0(ms) 以前版本(ms) 与以前的比率
df1 > df2 13.32 125.35 0.1063
df1 * df2 21.71 36.63 0.5928
df1 + df2 22.04 36.50 0.6039

强烈建议您安装这两个库。有关更多安装信息,请参阅Recommended Dependencies一节。

Flexible binary operations

使用pandas数据结构之间的二进制操作,有两个关键点:

  • 在较高(例如DataFrame)和较低维(例如系列)对象之间的广播行为。
  • 计算中缺少数据

我们将演示如何独立地管理这些问题,虽然他们可以同时处理。

Matching / broadcasting behavior

DataFrame具有方法add()sub()mul()div()和相关函数radd()rsub(),...for carrying out binary operations.对于广播行为,系列输入是主要兴趣。使用这些函数,您可以通过关键字在索引上进行匹配:

In [14]: df = pd.DataFrame({'one' : pd.Series(np.random.randn(3), index=['a', 'b', 'c']),
   ....:                    'two' : pd.Series(np.random.randn(4), index=['a', 'b', 'c', 'd']),
   ....:                    'three' : pd.Series(np.random.randn(3), index=['b', 'c', 'd'])})
   ....: 

In [15]: df
Out[15]: 
        one     three       two
a -0.626544       NaN -0.351587
b -0.138894 -0.177289  1.136249
c  0.011617  0.462215 -0.448789
d       NaN  1.124472 -1.101558

In [16]: row = df.ix[1]

In [17]: column = df['two']

In [18]: df.sub(row, axis='columns')
Out[18]: 
        one     three       two
a -0.487650       NaN -1.487837
b  0.000000  0.000000  0.000000
c  0.150512  0.639504 -1.585038
d       NaN  1.301762 -2.237808

In [19]: df.sub(row, axis=1)
Out[19]: 
        one     three       two
a -0.487650       NaN -1.487837
b  0.000000  0.000000  0.000000
c  0.150512  0.639504 -1.585038
d       NaN  1.301762 -2.237808

In [20]: df.sub(column, axis='index')
Out[20]: 
        one     three  two
a -0.274957       NaN  0.0
b -1.275144 -1.313539  0.0
c  0.460406  0.911003  0.0
d       NaN  2.226031  0.0

In [21]: df.sub(column, axis=0)
Out[21]: 
        one     three  two
a -0.274957       NaN  0.0
b -1.275144 -1.313539  0.0
c  0.460406  0.911003  0.0
d       NaN  2.226031  0.0

此外,您可以将多索引DataFrame的级别与系列对齐。

In [22]: dfmi = df.copy()

In [23]: dfmi.index = pd.MultiIndex.from_tuples([(1,'a'),(1,'b'),(1,'c'),(2,'a')],
   ....:                                        names=['first','second'])
   ....: 

In [24]: dfmi.sub(column, axis=0, level='second')
Out[24]: 
                   one     three       two
first second                              
1     a      -0.274957       NaN  0.000000
      b      -1.275144 -1.313539  0.000000
      c       0.460406  0.911003  0.000000
2     a            NaN  1.476060 -0.749971

使用Panel,描述匹配行为有点困难,因此算术方法改为(也许令人困惑?)您可以选择指定广播轴例如,假设我们希望在特定轴上贬低数据。这可以通过在一个轴上取平均值并在同一轴上广播来实现:

In [25]: major_mean = wp.mean(axis='major')

In [26]: major_mean
Out[26]: 
      Item1     Item2
A -0.546569 -0.260774
B  0.492478  0.147993
C -0.649010 -0.532794
D  0.176307  0.623812

In [27]: wp.sub(major_mean, axis='major')
Out[27]: 
<class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 5 (major_axis) x 4 (minor_axis)
Items axis: Item1 to Item2
Major_axis axis: 2000-01-01 00:00:00 to 2000-01-05 00:00:00
Minor_axis axis: A to D

对于axis="items"axis="minor"也是如此。

注意

我可以确信,使DataFrame方法中的参数与Panel的广播行为相匹配。虽然它需要一个过渡期,以便用户可以更改他们的代码...

系列和索引也支持divmod()内置。该函数进行底格除法和模运算,同时返回与左手相同类型的两元组。例如:

In [28]: s = pd.Series(np.arange(10))

In [29]: s
Out[29]: 
0    0
1    1
2    2
3    3
4    4
5    5
6    6
7    7
8    8
9    9
dtype: int64

In [30]: div, rem = divmod(s, 3)

In [31]: div
Out[31]: 
0    0
1    0
2    0
3    1
4    1
5    1
6    2
7    2
8    2
9    3
dtype: int64

In [32]: rem
Out[32]: 
0    0
1    1
2    2
3    0
4    1
5    2
6    0
7    1
8    2
9    0
dtype: int64

In [33]: idx = pd.Index(np.arange(10))

In [34]: idx
Out[34]: Int64Index([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype='int64')

In [35]: div, rem = divmod(idx, 3)

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

In [37]: rem
Out[37]: Int64Index([0, 1, 2, 0, 1, 2, 0, 1, 2, 0], dtype='int64')

divmod()也可以对数据结构中的元素分开操作:

In [38]: div, rem = divmod(s, [2, 2, 3, 3, 4, 4, 5, 5, 6, 6])

In [39]: div
Out[39]: 
0    0
1    0
2    0
3    1
4    1
5    1
6    1
7    1
8    1
9    1
dtype: int64

In [40]: rem
Out[40]: 
0    0
1    1
2    2
3    0
4    0
5    1
6    1
7    2
8    2
9    3
dtype: int64

Missing data / operations with fill values

在Series和DataFrame中(Panel不支持),算术函数可以选择输入fill_value,即当一个位置的最多一个值丢失时要替换的值。例如,当添加两个DataFrame对象时,您可能希望将NaN视为0,除非两个DataFrames都缺少该值,在这种情况下,结果将是NaN(您可以稍后使用fillna

In [41]: df
Out[41]: 
        one     three       two
a -0.626544       NaN -0.351587
b -0.138894 -0.177289  1.136249
c  0.011617  0.462215 -0.448789
d       NaN  1.124472 -1.101558

In [42]: df2
Out[42]: 
        one     three       two
a -0.626544  1.000000 -0.351587
b -0.138894 -0.177289  1.136249
c  0.011617  0.462215 -0.448789
d       NaN  1.124472 -1.101558

In [43]: df + df2
Out[43]: 
        one     three       two
a -1.253088       NaN -0.703174
b -0.277789 -0.354579  2.272499
c  0.023235  0.924429 -0.897577
d       NaN  2.248945 -2.203116

In [44]: df.add(df2, fill_value=0)
Out[44]: 
        one     three       two
a -1.253088  1.000000 -0.703174
b -0.277789 -0.354579  2.272499
c  0.023235  0.924429 -0.897577
d       NaN  2.248945 -2.203116

Flexible Comparisons

从v0.8开始,pandas将二进制比较方法eq,ne,lt,gt,le和ge引入到Series和DataFrame,其行为类似于上述二进制算术运算:

In [45]: df.gt(df2)
Out[45]: 
     one  three    two
a  False  False  False
b  False  False  False
c  False  False  False
d  False  False  False

In [46]: df2.ne(df)
Out[46]: 
     one  three    two
a  False   True  False
b  False  False  False
c  False  False  False
d   True  False  False

这些操作产生与左侧输入相同类型的pandas对象,如果是dtype bool这些boolean对象可用于索引操作,请参阅here

Boolean Reductions

您可以应用减少:emptyany()all()bool()

In [47]: (df > 0).all()
Out[47]: 
one      False
three    False
two      False
dtype: bool

In [48]: (df > 0).any()
Out[48]: 
one      True
three    True
two      True
dtype: bool

您可以减少到最终的布尔值。

In [49]: (df > 0).any().any()
Out[49]: True

您可以通过empty属性测试一个pandas对象是否为空。

In [50]: df.empty
Out[50]: False

In [51]: pd.DataFrame(columns=list('ABC')).empty
Out[51]: True

要在布尔上下文中评估单元素熊猫对象,请使用方法bool()

In [52]: pd.Series([True]).bool()
Out[52]: True

In [53]: pd.Series([False]).bool()
Out[53]: False

In [54]: pd.DataFrame([[True]]).bool()
Out[54]: True

In [55]: pd.DataFrame([[False]]).bool()
Out[55]: False

警告

您可能会试图执行以下操作:

>>> if df:
     ...

要么

>>> df and df2

上面两个操作都会导致下面的错误

ValueError: The truth value of an array is ambiguous. Use a.empty, a.any() or a.all().

有关详细讨论,请参阅gotchas

Comparing if objects are equivalent

通常,您可能会发现有多种方法来计算相同的结果。作为一个简单的例子,考虑df+dfdf*2为了测试这两个计算产生相同的结果,给定上面所示的工具,你可以想象使用(df + df == df * 2 ).all()但实际上,这个表达式是False:

In [56]: df+df == df*2
Out[56]: 
     one  three   two
a   True  False  True
b   True   True  True
c   True   True  True
d  False   True  True

In [57]: (df+df == df*2).all()
Out[57]: 
one      False
three    False
two       True
dtype: bool

请注意,布尔DataFrame df + df == df * 2包含一些False值!这是因为NaN不等于自身:

In [58]: np.nan == np.nan
Out[58]: False

因此,从v0.13.1开始,NDFrames(如Series,DataFrames和Panels)有一个用于测试等式的equals()方法,其中相应位置的NaN被视为相等。

In [59]: (df+df).equals(df*2)
Out[59]: True

请注意,Series或DataFrame索引需要按相同的顺序使等于True:

In [60]: df1 = pd.DataFrame({'col':['foo', 0, np.nan]})

In [61]: df2 = pd.DataFrame({'col':[np.nan, 0, 'foo']}, index=[2,1,0])

In [62]: df1.equals(df2)
Out[62]: False

In [63]: df1.equals(df2.sort_index())
Out[63]: True

Comparing array-like objects

当将pandas数据结构与标量值进行比较时,可以方便地进行逐个元素的比较:

In [64]: pd.Series(['foo', 'bar', 'baz']) == 'foo'
Out[64]: 
0     True
1    False
2    False
dtype: bool

In [65]: pd.Index(['foo', 'bar', 'baz']) == 'foo'
Out[65]: array([ True, False, False], dtype=bool)

Pandas还处理相同长度的不同数组类对象之间的元素方面的比较:

In [66]: pd.Series(['foo', 'bar', 'baz']) == pd.Index(['foo', 'bar', 'qux'])
Out[66]: 
0     True
1     True
2    False
dtype: bool

In [67]: pd.Series(['foo', 'bar', 'baz']) == np.array(['foo', 'bar', 'qux'])
Out[67]: 
0     True
1     True
2    False
dtype: bool

尝试比较不同长度的IndexSeries对象将产生一个ValueError:

In [55]: pd.Series(['foo', 'bar', 'baz']) == pd.Series(['foo', 'bar'])
ValueError: Series lengths must match to compare

In [56]: pd.Series(['foo', 'bar', 'baz']) == pd.Series(['foo'])
ValueError: Series lengths must match to compare

请注意,这不同于可以广播比较的numpy行为:

In [68]: np.array([1, 2, 3]) == np.array([2])
Out[68]: array([False,  True, False], dtype=bool)

或者如果广播不能完成,它可以返回False:

In [69]: np.array([1, 2, 3]) == np.array([1, 2])
Out[69]: False

Combining overlapping data sets

当具有两个DataFrame时,其中一个数据质量优于另一个,那么这两个DataFrame的组合可能会有些问题。一个示例如下:表示特定经济指标的两个数据系列,其中一个被认为具有“更高的质量”。然而,较低质量的系列可能在历史上进一步延伸或具有更完整的数据覆盖。因此,我们希望组合两个DataFrame对象,其中一个DataFrame中的缺失值有条件地使用来自其他DataFrame的类似标签值填充。实现此操作的函数是combine_first(),我们说明:

In [70]: df1 = pd.DataFrame({'A' : [1., np.nan, 3., 5., np.nan],
   ....:                     'B' : [np.nan, 2., 3., np.nan, 6.]})
   ....: 

In [71]: df2 = pd.DataFrame({'A' : [5., 2., 4., np.nan, 3., 7.],
   ....:                     'B' : [np.nan, np.nan, 3., 4., 6., 8.]})
   ....: 

In [72]: df1
Out[72]: 
     A    B
0  1.0  NaN
1  NaN  2.0
2  3.0  3.0
3  5.0  NaN
4  NaN  6.0

In [73]: df2
Out[73]: 
     A    B
0  5.0  NaN
1  2.0  NaN
2  4.0  3.0
3  NaN  4.0
4  3.0  6.0
5  7.0  8.0

In [74]: df1.combine_first(df2)
Out[74]: 
     A    B
0  1.0  NaN
1  2.0  2.0
2  3.0  3.0
3  5.0  4.0
4  3.0  6.0
5  7.0  8.0

General DataFrame Combine

上面的combine_first()方法调用更通用的DataFrame方法combine()此方法接受另一个DataFrame和组合器函数,对齐输入DataFrame,然后传递Series的组合器函数对(即名称相同的列)。

因此,例如,如上所述再现combine_first()

In [75]: combiner = lambda x, y: np.where(pd.isnull(x), y, x)

In [76]: df1.combine(df2, combiner)
Out[76]: 
     A    B
0  1.0  NaN
1  2.0  2.0
2  3.0  3.0
3  5.0  4.0
4  3.0  6.0
5  7.0  8.0

Descriptive statistics

用于计算SeriesDataFramePanel上的描述统计和其他相关操作的大量方法。这些中的大多数是像sum()mean()quantile()的聚合(因此产生较低维的结果),但是其中一些像cumsum()cumprod()会生成相同大小的对象。一般来说,这些方法采用参数,就像ndarray。{sum,std,...},但轴可以通过名称或整数指定:

  • Series:无需轴参数
  • DataFrame:“index”(axis = 0,默认值),“columns”(axis = 1)
  • 面板:“items”(axis = 0),“major”(轴= 1,默认),“minor”

例如:

In [77]: df
Out[77]: 
        one     three       two
a -0.626544       NaN -0.351587
b -0.138894 -0.177289  1.136249
c  0.011617  0.462215 -0.448789
d       NaN  1.124472 -1.101558

In [78]: df.mean(0)
Out[78]: 
one     -0.251274
three    0.469799
two     -0.191421
dtype: float64

In [79]: df.mean(1)
Out[79]: 
a   -0.489066
b    0.273355
c    0.008348
d    0.011457
dtype: float64

所有这些方法都有一个skipna选项,指示是否排除缺失的数据(默认情况下True):

In [80]: df.sum(0, skipna=False)
Out[80]: 
one           NaN
three         NaN
two     -0.765684
dtype: float64

In [81]: df.sum(axis=1, skipna=True)
Out[81]: 
a   -0.978131
b    0.820066
c    0.025044
d    0.022914
dtype: float64

结合广播/算术行为,可以非常简明地描述各种统计过程,如标准化(呈现数据零均值和标准偏差1):

In [82]: ts_stand = (df - df.mean()) / df.std()

In [83]: ts_stand.std()
Out[83]: 
one      1.0
three    1.0
two      1.0
dtype: float64

In [84]: xs_stand = df.sub(df.mean(1), axis=0).div(df.std(1), axis=0)

In [85]: xs_stand.std(1)
Out[85]: 
a    1.0
b    1.0
c    1.0
d    1.0
dtype: float64

注意,像cumsum()cumprod()的方法保留NA值的位置:

In [86]: df.cumsum()
Out[86]: 
        one     three       two
a -0.626544       NaN -0.351587
b -0.765438 -0.177289  0.784662
c -0.753821  0.284925  0.335874
d       NaN  1.409398 -0.765684

这里是一个常用功能的快速参考汇总表。每个还采用可选的level参数,该参数仅在对象具有hierarchical index时适用。

功能 描述
count 非零观察数
sum 值的总和
mean 值的平均值
mad 平均绝对偏差
median 值的算术中值
min 最低
max 最大值
mode 模式
abs 绝对值
prod 值的产物
std 贝塞尔校正样本标准偏差
var 无偏差
sem 平均值的标准误差
skew 样品偏斜度(第三动量)
kurt 样品峰度(第4圈)
quantile 样本分位数(值%)
cumsum 累积和
cumprod 累积乘积
cummax 累积最大值
cummin 累积最小值

请注意,偶尔,一些NumPy方法(如meanstdsum)将默认排除系列输入上的NA:

In [87]: np.mean(df['one'])
Out[87]: -0.2512736517583951

In [88]: np.mean(df['one'].values)
Out[88]: nan

Series也有一个方法nunique(),它将返回唯一的非空值的数量:

In [89]: series = pd.Series(np.random.randn(500))

In [90]: series[20:500] = np.nan

In [91]: series[10:20]  = 5

In [92]: series.nunique()
Out[92]: 11

Summarizing data: describe

有一个方便的describe()函数,用于计算关于数据框架的一系列或多个列的各种汇总统计数据(当然不包括NAs):

In [93]: series = pd.Series(np.random.randn(1000))

In [94]: series[::2] = np.nan

In [95]: series.describe()
Out[95]: 
count    500.000000
mean      -0.039663
std        1.069371
min       -3.463789
25%       -0.731101
50%       -0.058918
75%        0.672758
max        3.120271
dtype: float64

In [96]: frame = pd.DataFrame(np.random.randn(1000, 5), columns=['a', 'b', 'c', 'd', 'e'])

In [97]: frame.ix[::2] = np.nan

In [98]: frame.describe()
Out[98]: 
                a           b           c           d           e
count  500.000000  500.000000  500.000000  500.000000  500.000000
mean     0.000954   -0.044014    0.075936   -0.003679    0.020751
std      1.005133    0.974882    0.967432    1.004732    0.963812
min     -3.010899   -2.782760   -3.401252   -2.944925   -3.794127
25%     -0.682900   -0.681161   -0.528190   -0.663503   -0.615717
50%     -0.001651   -0.006279    0.040098   -0.003378    0.006282
75%      0.656439    0.632852    0.717919    0.687214    0.653423
max      3.007143    2.627688    2.702490    2.850852    3.072117

您可以选择要包括在输出中的特定百分位数:

In [99]: series.describe(percentiles=[.05, .25, .75, .95])
Out[99]: 
count    500.000000
mean      -0.039663
std        1.069371
min       -3.463789
5%        -1.741334
25%       -0.731101
50%       -0.058918
75%        0.672758
95%        1.854383
max        3.120271
dtype: float64

默认情况下,始终包括中值。

对于非数值系列对象,describe()将给出唯一值数量和最常出现的值的简单摘要:

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

In [101]: s.describe()
Out[101]: 
count     9
unique    4
top       a
freq      5
dtype: object

请注意,在混合类型DataFrame对象上,describe()将限制摘要仅包含数字列,如果没有,则只包含分类列:

In [102]: frame = pd.DataFrame({'a': ['Yes', 'Yes', 'No', 'No'], 'b': range(4)})

In [103]: frame.describe()
Out[103]: 
              b
count  4.000000
mean   1.500000
std    1.290994
min    0.000000
25%    0.750000
50%    1.500000
75%    2.250000
max    3.000000

可以通过提供include / exclude参数的类型列表来控制此行为。也可以使用特殊值all

In [104]: frame.describe(include=['object'])
Out[104]: 
         a
count    4
unique   2
top     No
freq     2

In [105]: frame.describe(include=['number'])
Out[105]: 
              b
count  4.000000
mean   1.500000
std    1.290994
min    0.000000
25%    0.750000
50%    1.500000
75%    2.250000
max    3.000000

In [106]: frame.describe(include='all')
Out[106]: 
          a         b
count     4  4.000000
unique    2       NaN
top      No       NaN
freq      2       NaN
mean    NaN  1.500000
std     NaN  1.290994
min     NaN  0.000000
25%     NaN  0.750000
50%     NaN  1.500000
75%     NaN  2.250000
max     NaN  3.000000

该功能依赖于select_dtypes有关接受的输入的详细信息,请参阅此处。

Index of Min/Max Values

Series和DataFrame上的idxmin()idxmax()函数使用最小和最大对应值计算索引标签:

In [107]: s1 = pd.Series(np.random.randn(5))

In [108]: s1
Out[108]: 
0   -0.872725
1    1.522411
2    0.080594
3   -1.676067
4    0.435804
dtype: float64

In [109]: s1.idxmin(), s1.idxmax()
Out[109]: (3, 1)

In [110]: df1 = pd.DataFrame(np.random.randn(5,3), columns=['A','B','C'])

In [111]: df1
Out[111]: 
          A         B         C
0  0.445734 -1.649461  0.169660
1  1.246181  0.131682 -2.001988
2 -1.273023  0.870502  0.214583
3  0.088452 -0.173364  1.207466
4  0.546121  0.409515 -0.310515

In [112]: df1.idxmin(axis=0)
Out[112]: 
A    2
B    0
C    1
dtype: int64

In [113]: df1.idxmax(axis=1)
Out[113]: 
0    A
1    A
2    B
3    C
4    A
dtype: object

当有多个行(或列)匹配最小值或最大值时,idxmin()idxmax()返回第一个匹配索引:

In [114]: df3 = pd.DataFrame([2, 1, 1, 3, np.nan], columns=['A'], index=list('edcba'))

In [115]: df3
Out[115]: 
     A
e  2.0
d  1.0
c  1.0
b  3.0
a  NaN

In [116]: df3['A'].idxmin()
Out[116]: 'd'

注意

在NumPy中,idxminidxmax称为argminargmax

Value counts (histogramming) / Mode

value_counts()系列方法和顶级函数计算一维数组值的直方图。它也可以用作常规数组上的函数:

In [117]: data = np.random.randint(0, 7, size=50)

In [118]: data
Out[118]: 
array([5, 3, 2, 2, 1, 4, 0, 4, 0, 2, 0, 6, 4, 1, 6, 3, 3, 0, 2, 1, 0, 5, 5,
       3, 6, 1, 5, 6, 2, 0, 0, 6, 3, 3, 5, 0, 4, 3, 3, 3, 0, 6, 1, 3, 5, 5,
       0, 4, 0, 6])

In [119]: s = pd.Series(data)

In [120]: s.value_counts()
Out[120]: 
0    11
3    10
6     7
5     7
4     5
2     5
1     5
dtype: int64

In [121]: pd.value_counts(data)
Out[121]: 
0    11
3    10
6     7
5     7
4     5
2     5
1     5
dtype: int64

类似地,您可以在Series或DataFrame中获取值的最频繁出现的值(模式):

In [122]: s5 = pd.Series([1, 1, 3, 3, 3, 5, 5, 7, 7, 7])

In [123]: s5.mode()
Out[123]: 
0    3
1    7
dtype: int64

In [124]: df5 = pd.DataFrame({"A": np.random.randint(0, 7, size=50),
   .....:                     "B": np.random.randint(-10, 15, size=50)})
   .....: 

In [125]: df5.mode()
Out[125]: 
   A  B
0  1 -5

Discretization and quantiling

可以使用cut()(基于值的分档)和qcut()(基于样本分位数的分档)函数来离散连续值:

In [126]: arr = np.random.randn(20)

In [127]: factor = pd.cut(arr, 4)

In [128]: factor
Out[128]: 
[(-0.645, 0.336], (-2.61, -1.626], (-1.626, -0.645], (-1.626, -0.645], (-1.626, -0.645], ..., (0.336, 1.316], (0.336, 1.316], (0.336, 1.316], (0.336, 1.316], (-2.61, -1.626]]
Length: 20
Categories (4, object): [(-2.61, -1.626] < (-1.626, -0.645] < (-0.645, 0.336] < (0.336, 1.316]]

In [129]: factor = pd.cut(arr, [-5, -1, 0, 1, 5])

In [130]: factor
Out[130]: 
[(-1, 0], (-5, -1], (-1, 0], (-5, -1], (-1, 0], ..., (0, 1], (1, 5], (0, 1], (0, 1], (-5, -1]]
Length: 20
Categories (4, object): [(-5, -1] < (-1, 0] < (0, 1] < (1, 5]]

qcut()计算样本分位数。例如,我们可以将一些正态分布的数据分割成等大小的四分位数,如下所示:

In [131]: arr = np.random.randn(30)

In [132]: factor = pd.qcut(arr, [0, .25, .5, .75, 1])

In [133]: factor
Out[133]: 
[(-0.139, 1.00736], (1.00736, 1.976], (1.00736, 1.976], [-1.0705, -0.439], [-1.0705, -0.439], ..., (1.00736, 1.976], [-1.0705, -0.439], (-0.439, -0.139], (-0.439, -0.139], (-0.439, -0.139]]
Length: 30
Categories (4, object): [[-1.0705, -0.439] < (-0.439, -0.139] < (-0.139, 1.00736] < (1.00736, 1.976]]

In [134]: pd.value_counts(factor)
Out[134]: 
(1.00736, 1.976]     8
[-1.0705, -0.439]    8
(-0.139, 1.00736]    7
(-0.439, -0.139]     7
dtype: int64

我们还可以传递无限值来定义bin:

In [135]: arr = np.random.randn(20)

In [136]: factor = pd.cut(arr, [-np.inf, 0, np.inf])

In [137]: factor
Out[137]: 
[(-inf, 0], (0, inf], (0, inf], (0, inf], (-inf, 0], ..., (-inf, 0], (0, inf], (-inf, 0], (-inf, 0], (0, inf]]
Length: 20
Categories (2, object): [(-inf, 0] < (0, inf]]

Function application

要将自己的或另一个库的函数应用于pandas对象,您应该注意以下三个方法。使用的适当方法取决于您的函数是希望对整个DataFrame还是Series,行或列方式或元素方式进行操作。

  1. 表格函数应用pipe()
  2. 行或列函数应用程序apply()
  3. 元素函数应用程序:applymap()

Tablewise Function Application

版本0.16.2中的新功能。

DataFramesSeries当然可以传递到函数中。但是,如果函数需要在链中调用,请考虑使用pipe()方法。比较以下内容

# f, g, and h are functions taking and returning ``DataFrames``
>>> f(g(h(df), arg1=1), arg2=2, arg3=3)

与等效

>>> (df.pipe(h)
       .pipe(g, arg1=1)
       .pipe(f, arg2=2, arg3=3)
    )

pandas 鼓励第二种风格,这被称为方法链。pipe可以方便地在方法链中使用自己或另一个库的函数,以及pandas的方法。

在上述示例中,函数fgh各自将DataFrame预期为第一个位置参数。如果你希望应用的函数把它的数据,例如,第二个参数怎么办?在这种情况下,使用元组(可调用, data_keyword)提供pipe.pipe会将DataFrame路由到元组中指定的参数。

例如,我们可以使用statsmodels拟合回归。他们的API期望公式优先,并且将DataFrame作为第二个参数,data我们将关键字对(sm.poisson, 'data')传递到pipe

In [138]: import statsmodels.formula.api as sm

In [139]: bb = pd.read_csv('data/baseball.csv', index_col='id')

In [140]: (bb.query('h > 0')
   .....:    .assign(ln_h = lambda df: np.log(df.h))
   .....:    .pipe((sm.poisson, 'data'), 'hr ~ ln_h + year + g + C(lg)')
   .....:    .fit()
   .....:    .summary()
   .....: )
   .....: 
Optimization terminated successfully.
         Current function value: 2.116284
         Iterations 24
Out[140]: 
<class 'statsmodels.iolib.summary.Summary'>
"""
                          Poisson Regression Results                          
==============================================================================
Dep. Variable:                     hr   No. Observations:                   68
Model:                        Poisson   Df Residuals:                       63
Method:                           MLE   Df Model:                            4
Date:                Sat, 24 Dec 2016   Pseudo R-squ.:                  0.6878
Time:                        18:31:33   Log-Likelihood:                -143.91
converged:                       True   LL-Null:                       -460.91
                                        LLR p-value:                6.774e-136
===============================================================================
                  coef    std err          z      P>|z|      [95.0% Conf. Int.]
-------------------------------------------------------------------------------
Intercept   -1267.3636    457.867     -2.768      0.006     -2164.767  -369.960
C(lg)[T.NL]    -0.2057      0.101     -2.044      0.041        -0.403    -0.008
ln_h            0.9280      0.191      4.866      0.000         0.554     1.302
year            0.6301      0.228      2.762      0.006         0.183     1.077
g               0.0099      0.004      2.754      0.006         0.003     0.017
===============================================================================
"""

管道方法受unix管道的启发,最近dplyrmagrittr,其引入了流行的(%>%) )运算符Rpipe这里是相当干净,感觉在家里在python。我们建议您查看源代码(pd.DataFrame.pipe??在IPython)。

Row or Column-wise Function Application

可以使用apply()方法沿着DataFrame或Panel的轴应用任意函数,与描述性统计方法一样,它采用可选的axis参数:

In [141]: df.apply(np.mean)
Out[141]: 
one     -0.251274
three    0.469799
two     -0.191421
dtype: float64

In [142]: df.apply(np.mean, axis=1)
Out[142]: 
a   -0.489066
b    0.273355
c    0.008348
d    0.011457
dtype: float64

In [143]: df.apply(lambda x: x.max() - x.min())
Out[143]: 
one      0.638161
three    1.301762
two      2.237808
dtype: float64

In [144]: df.apply(np.cumsum)
Out[144]: 
        one     three       two
a -0.626544       NaN -0.351587
b -0.765438 -0.177289  0.784662
c -0.753821  0.284925  0.335874
d       NaN  1.409398 -0.765684

In [145]: df.apply(np.exp)
Out[145]: 
        one     three       two
a  0.534436       NaN  0.703570
b  0.870320  0.837537  3.115063
c  1.011685  1.587586  0.638401
d       NaN  3.078592  0.332353

根据传递给apply()的函数的返回类型,结果将为较低维或相同维。

apply()结合一些聪明可以用来回答关于数据集的许多问题。例如,假设我们要提取每个列的最大值出现的日期:

In [146]: tsdf = pd.DataFrame(np.random.randn(1000, 3), columns=['A', 'B', 'C'],
   .....:                     index=pd.date_range('1/1/2000', periods=1000))
   .....: 

In [147]: tsdf.apply(lambda x: x.idxmax())
Out[147]: 
A   2001-04-27
B   2002-06-02
C   2000-04-02
dtype: datetime64[ns]

您还可以向apply()方法传递其他参数和关键字参数。例如,考虑以下您要应用的功能:

def subtract_and_divide(x, sub, divide=1):
    return (x - sub) / divide

然后,您可以应用此功能,如下所示:

df.apply(subtract_and_divide, args=(5,), divide=3)

另一个有用的功能是能够通过Series方法对每个列或行执行一些Series操作:

In [148]: tsdf
Out[148]: 
                   A         B         C
2000-01-01  1.796883 -0.930690  3.542846
2000-01-02 -1.242888 -0.695279 -1.000884
2000-01-03 -0.720299  0.546303 -0.082042
2000-01-04       NaN       NaN       NaN
2000-01-05       NaN       NaN       NaN
2000-01-06       NaN       NaN       NaN
2000-01-07       NaN       NaN       NaN
2000-01-08 -0.527402  0.933507  0.129646
2000-01-09 -0.338903 -1.265452 -1.969004
2000-01-10  0.532566  0.341548  0.150493

In [149]: tsdf.apply(pd.Series.interpolate)
Out[149]: 
                   A         B         C
2000-01-01  1.796883 -0.930690  3.542846
2000-01-02 -1.242888 -0.695279 -1.000884
2000-01-03 -0.720299  0.546303 -0.082042
2000-01-04 -0.681720  0.623743 -0.039704
2000-01-05 -0.643140  0.701184  0.002633
2000-01-06 -0.604561  0.778625  0.044971
2000-01-07 -0.565982  0.856066  0.087309
2000-01-08 -0.527402  0.933507  0.129646
2000-01-09 -0.338903 -1.265452 -1.969004
2000-01-10  0.532566  0.341548  0.150493

最后,apply()默认使用一个参数raw,它默认为False,它在应用函数之前将每个行或列转换为一个Series。当设置为True时,传递的函数将接收一个ndarray对象,如果您不需要索引功能,这将具有积极的性能影响。

也可以看看

GroupBy部分演示了相关的灵活功能,可按照某些标准进行分组,应用结果并将结果合并到Series,DataFrame等。

Applying elementwise Python functions

由于并非所有函数都可以向量化(接受NumPy数组并返回另一个数组或值),DataFrame上的方法applymap()和类似的map()例如:

In [150]: df4
Out[150]: 
        one     three       two
a -0.626544       NaN -0.351587
b -0.138894 -0.177289  1.136249
c  0.011617  0.462215 -0.448789
d       NaN  1.124472 -1.101558

In [151]: f = lambda x: len(str(x))

In [152]: df4['one'].map(f)
Out[152]: 
a    14
b    15
c    15
d     3
Name: one, dtype: int64

In [153]: df4.applymap(f)
Out[153]: 
   one  three  two
a   14      3   15
b   15     15   11
c   15     14   15
d    3     13   14

Series.map()有一个附加功能,它可以用于轻松地“链接”或“映射”由辅助系列定义的值。这与merging/joining functionality密切相关:

In [154]: s = pd.Series(['six', 'seven', 'six', 'seven', 'six'],
   .....:               index=['a', 'b', 'c', 'd', 'e'])
   .....: 

In [155]: t = pd.Series({'six' : 6., 'seven' : 7.})

In [156]: s
Out[156]: 
a      six
b    seven
c      six
d    seven
e      six
dtype: object

In [157]: s.map(t)
Out[157]: 
a    6.0
b    7.0
c    6.0
d    7.0
e    6.0
dtype: float64

Applying with a Panel

应用Panel会将Series传递给应用的函数。如果应用函数返回Series,应用程序的结果将是Panel如果应用函数减少到标量,应用程序的结果将是DataFrame

注意

Prior to 0.13.1 apply on a Panel would only work on ufuncs (e.g. np.sum/np.max).

In [158]: import pandas.util.testing as tm

In [159]: panel = tm.makePanel(5)

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

In [161]: panel['ItemA']
Out[161]: 
                   A         B         C         D
2000-01-03  0.330418  1.893177  0.801111  0.528154
2000-01-04  1.761200  0.170247  0.445614 -0.029371
2000-01-05  0.567133 -0.916844  1.453046 -0.631117
2000-01-06 -0.251020  0.835024  2.430373 -0.172441
2000-01-07  1.020099  1.259919  0.653093 -1.020485

转换适用。

In [162]: result = panel.apply(lambda x: x*2, axis='items')

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

In [164]: result['ItemA']
Out[164]: 
                   A         B         C         D
2000-01-03  0.660836  3.786354  1.602222  1.056308
2000-01-04  3.522400  0.340494  0.891228 -0.058742
2000-01-05  1.134266 -1.833689  2.906092 -1.262234
2000-01-06 -0.502039  1.670047  4.860747 -0.344882
2000-01-07  2.040199  2.519838  1.306185 -2.040969

还原操作。

In [165]: panel.apply(lambda x: x.dtype, axis='items')
Out[165]: 
                  A        B        C        D
2000-01-03  float64  float64  float64  float64
2000-01-04  float64  float64  float64  float64
2000-01-05  float64  float64  float64  float64
2000-01-06  float64  float64  float64  float64
2000-01-07  float64  float64  float64  float64

类似的减少类型操作

In [166]: panel.apply(lambda x: x.sum(), axis='major_axis')
Out[166]: 
      ItemA     ItemB     ItemC
A  3.427831 -2.581431  0.840809
B  3.241522 -1.409935 -1.114512
C  5.783237  0.319672 -0.431906
D -1.325260 -2.914834  0.857043

这最后的减少等同于

In [167]: panel.sum('major_axis')
Out[167]: 
      ItemA     ItemB     ItemC
A  3.427831 -2.581431  0.840809
B  3.241522 -1.409935 -1.114512
C  5.783237  0.319672 -0.431906
D -1.325260 -2.914834  0.857043

返回Panel的转换操作,但计算major_axis中的z分数。

In [168]: result = panel.apply(
   .....:            lambda x: (x-x.mean())/x.std(),
   .....:            axis='major_axis')
   .....: 

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

In [170]: result['ItemA']
Out[170]: 
                   A         B         C         D
2000-01-03 -0.469761  1.156225 -0.441347  1.341731
2000-01-04  1.422763 -0.444015 -0.882647  0.398661
2000-01-05 -0.156654 -1.453694  0.367936 -0.619210
2000-01-06 -1.238841  0.173423  1.581149  0.156654
2000-01-07  0.442494  0.568061 -0.625091 -1.277837

应用也可以接受axis参数中的多个轴。这会将横截面的DataFrame传递给应用函数。

In [171]: f = lambda x: ((x.T-x.mean(1))/x.std(1)).T

In [172]: result = panel.apply(f, axis = ['items','major_axis'])

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

In [174]: result.loc[:,:,'ItemA']
Out[174]: 
                   A         B         C         D
2000-01-03  0.864236  1.132969  0.557316  0.575106
2000-01-04  0.795745  0.652527  0.534808 -0.070674
2000-01-05 -0.310864  0.558627  1.086688 -1.051477
2000-01-06 -0.001065  0.832460  0.846006  0.043602
2000-01-07  1.128946  1.152469 -0.218186 -0.891680

这相当于以下内容

In [175]: result = pd.Panel(dict([ (ax, f(panel.loc[:,:,ax]))
   .....:                         for ax in panel.minor_axis ]))
   .....: 

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

In [177]: result.loc[:,:,'ItemA']
Out[177]: 
                   A         B         C         D
2000-01-03  0.864236  1.132969  0.557316  0.575106
2000-01-04  0.795745  0.652527  0.534808 -0.070674
2000-01-05 -0.310864  0.558627  1.086688 -1.051477
2000-01-06 -0.001065  0.832460  0.846006  0.043602
2000-01-07  1.128946  1.152469 -0.218186 -0.891680

Reindexing and altering labels

reindex()是pandas中的基本数据对齐方法。它用于实现几乎所有依赖于标签对齐功能的其他功能。reindex通过指定的索引来匹配值有以下几个功能:

  • 重新排序现有数据以匹配一组新标签
  • 在没有该标签的数据的标签位置插入缺少值(NA)标记
  • 如果指定,使用逻辑(与使用时间序列数据非常相关),缺少标签的填充

这里有一个简单的例子:

In [178]: s = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])

In [179]: s
Out[179]: 
a   -1.010924
b   -0.672504
c   -1.139222
d    0.354653
e    0.563622
dtype: float64

In [180]: s.reindex(['e', 'b', 'f', 'd'])
Out[180]: 
e    0.563622
b   -0.672504
f         NaN
d    0.354653
dtype: float64

这里,f标签不包含在系列中,因此在结果中显示为NaN

使用DataFrame,您可以同时重新索引索引和列:

In [181]: df
Out[181]: 
        one     three       two
a -0.626544       NaN -0.351587
b -0.138894 -0.177289  1.136249
c  0.011617  0.462215 -0.448789
d       NaN  1.124472 -1.101558

In [182]: df.reindex(index=['c', 'f', 'b'], columns=['three', 'two', 'one'])
Out[182]: 
      three       two       one
c  0.462215 -0.448789  0.011617
f       NaN       NaN       NaN
b -0.177289  1.136249 -0.138894

为方便起见,您可以使用reindex_axis()方法,该方法使用标签和关键字axis参数。

请注意,包含实际轴标签的Index对象可以在对象之间共享因此,如果我们有一个Series和一个DataFrame,可以做到以下几点:

In [183]: rs = s.reindex(df.index)

In [184]: rs
Out[184]: 
a   -1.010924
b   -0.672504
c   -1.139222
d    0.354653
dtype: float64

In [185]: rs.index is df.index
Out[185]: True

这意味着重建索引系列的索引与DataFrame的索引是相同的Python对象。

也可以看看

MultiIndex / Advanced Indexing是一种更简洁的执行重建索引的方法。

注意

当编写性能敏感的代码时,有一个很好的理由花一些时间成为重建索引忍者:许多操作在预先对齐的数据上更快。在内部添加两个未对齐的DataFrames会触发重建索引步骤。对于探索性分析,您几乎不会注意到差异(因为reindex已被大量优化),但是当CPU周期在这里显示一些显式的reindex调用时, 。

Reindexing to align with another object

您可能希望获取一个对象,并将其轴重命名为与另一个对象相同的标签。虽然这种语法很简单,尽管很详细,但它是一个常见的操作,reindex_like()方法可以使这更简单:

In [186]: df2
Out[186]: 
        one       two
a -0.626544 -0.351587
b -0.138894  1.136249
c  0.011617 -0.448789

In [187]: df3
Out[187]: 
        one       two
a -0.375270 -0.463545
b  0.112379  1.024292
c  0.262891 -0.560746

In [188]: df.reindex_like(df2)
Out[188]: 
        one       two
a -0.626544 -0.351587
b -0.138894  1.136249
c  0.011617 -0.448789

Aligning objects with each other with align

align()方法是同时对齐两个对象的最快方法。它支持join参数(与joining and merging相关):

  • join='outer':获取索引的并集(默认)
  • join='left':使用调用对象的索引
  • join='right':使用传递的对象的索引
  • join='inner':与索引相交

它返回一个带有两个重建索引系列的元组:

In [189]: s = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])

In [190]: s1 = s[:4]

In [191]: s2 = s[1:]

In [192]: s1.align(s2)
Out[192]: 
(a   -0.365106
 b    1.092702
 c   -1.481449
 d    1.781190
 e         NaN
 dtype: float64, a         NaN
 b    1.092702
 c   -1.481449
 d    1.781190
 e   -0.031543
 dtype: float64)

In [193]: s1.align(s2, join='inner')
Out[193]: 
(b    1.092702
 c   -1.481449
 d    1.781190
 dtype: float64, b    1.092702
 c   -1.481449
 d    1.781190
 dtype: float64)

In [194]: s1.align(s2, join='left')
Out[194]: 
(a   -0.365106
 b    1.092702
 c   -1.481449
 d    1.781190
 dtype: float64, a         NaN
 b    1.092702
 c   -1.481449
 d    1.781190
 dtype: float64)

对于DataFrames,默认情况下,连接方法将应用于索引和列:

In [195]: df.align(df2, join='inner')
Out[195]: 
(        one       two
 a -0.626544 -0.351587
 b -0.138894  1.136249
 c  0.011617 -0.448789,         one       two
 a -0.626544 -0.351587
 b -0.138894  1.136249
 c  0.011617 -0.448789)

您也可以传递axis选项,仅在指定轴上对齐:

In [196]: df.align(df2, join='inner', axis=0)
Out[196]: 
(        one     three       two
 a -0.626544       NaN -0.351587
 b -0.138894 -0.177289  1.136249
 c  0.011617  0.462215 -0.448789,         one       two
 a -0.626544 -0.351587
 b -0.138894  1.136249
 c  0.011617 -0.448789)

如果将Series传递到DataFrame.align(),则可以选择使用axis参数在DataFrame的索引或列上对齐两个对象:

In [197]: df.align(df2.ix[0], axis=1)
Out[197]: 
(        one     three       two
 a -0.626544       NaN -0.351587
 b -0.138894 -0.177289  1.136249
 c  0.011617  0.462215 -0.448789
 d       NaN  1.124472 -1.101558, one     -0.626544
 three         NaN
 two     -0.351587
 Name: a, dtype: float64)

Filling while reindexing

reindex()采用可选参数method,它是从下表中选择的填充方法:

方法 行动
pad / ffill 向前填充值
bfill / backfill 向后填充值
最近 从最近的索引值填充

我们在一个简单的系列上说明这些填充方法:

In [198]: rng = pd.date_range('1/3/2000', periods=8)

In [199]: ts = pd.Series(np.random.randn(8), index=rng)

In [200]: ts2 = ts[[0, 3, 6]]

In [201]: ts
Out[201]: 
2000-01-03    0.480993
2000-01-04    0.604244
2000-01-05   -0.487265
2000-01-06    1.990533
2000-01-07    0.327007
2000-01-08    1.053639
2000-01-09   -2.927808
2000-01-10    0.082065
Freq: D, dtype: float64

In [202]: ts2
Out[202]: 
2000-01-03    0.480993
2000-01-06    1.990533
2000-01-09   -2.927808
dtype: float64

In [203]: ts2.reindex(ts.index)
Out[203]: 
2000-01-03    0.480993
2000-01-04         NaN
2000-01-05         NaN
2000-01-06    1.990533
2000-01-07         NaN
2000-01-08         NaN
2000-01-09   -2.927808
2000-01-10         NaN
Freq: D, dtype: float64

In [204]: ts2.reindex(ts.index, method='ffill')
Out[204]: 
2000-01-03    0.480993
2000-01-04    0.480993
2000-01-05    0.480993
2000-01-06    1.990533
2000-01-07    1.990533
2000-01-08    1.990533
2000-01-09   -2.927808
2000-01-10   -2.927808
Freq: D, dtype: float64

In [205]: ts2.reindex(ts.index, method='bfill')
Out[205]: 
2000-01-03    0.480993
2000-01-04    1.990533
2000-01-05    1.990533
2000-01-06    1.990533
2000-01-07   -2.927808
2000-01-08   -2.927808
2000-01-09   -2.927808
2000-01-10         NaN
Freq: D, dtype: float64

In [206]: ts2.reindex(ts.index, method='nearest')
Out[206]: 
2000-01-03    0.480993
2000-01-04    0.480993
2000-01-05    1.990533
2000-01-06    1.990533
2000-01-07    1.990533
2000-01-08   -2.927808
2000-01-09   -2.927808
2000-01-10   -2.927808
Freq: D, dtype: float64

这些方法要求索引有序增加或减少。

请注意,使用fillna(除了method='nearest')或interpolate可以实现相同的结果:

In [207]: ts2.reindex(ts.index).fillna(method='ffill')
Out[207]: 
2000-01-03    0.480993
2000-01-04    0.480993
2000-01-05    0.480993
2000-01-06    1.990533
2000-01-07    1.990533
2000-01-08    1.990533
2000-01-09   -2.927808
2000-01-10   -2.927808
Freq: D, dtype: float64

如果索引不是单调递增或递减,reindex()将引发ValueError。fillna()interpolate()不会对索引的顺序进行任何检查。

Limits on filling while reindexing

limittolerance参数在重建索引时提供对填充的额外控制。Limit指定连续匹配的最大计数:

In [208]: ts2.reindex(ts.index, method='ffill', limit=1)
Out[208]: 
2000-01-03    0.480993
2000-01-04    0.480993
2000-01-05         NaN
2000-01-06    1.990533
2000-01-07    1.990533
2000-01-08         NaN
2000-01-09   -2.927808
2000-01-10   -2.927808
Freq: D, dtype: float64

相反,公差指定索引和索引器值之间的最大距离:

In [209]: ts2.reindex(ts.index, method='ffill', tolerance='1 day')
Out[209]: 
2000-01-03    0.480993
2000-01-04    0.480993
2000-01-05         NaN
2000-01-06    1.990533
2000-01-07    1.990533
2000-01-08         NaN
2000-01-09   -2.927808
2000-01-10   -2.927808
Freq: D, dtype: float64

注意当在DatetimeIndexTimedeltaIndexPeriodIndex上使用时,tolerance将强制为Timedelta这允许您使用适当的字符串指定公差。

Dropping labels from an axis

reindex密切相关的方法是drop()函数。它从轴删除一组标签:

In [210]: df
Out[210]: 
        one     three       two
a -0.626544       NaN -0.351587
b -0.138894 -0.177289  1.136249
c  0.011617  0.462215 -0.448789
d       NaN  1.124472 -1.101558

In [211]: df.drop(['a', 'd'], axis=0)
Out[211]: 
        one     three       two
b -0.138894 -0.177289  1.136249
c  0.011617  0.462215 -0.448789

In [212]: df.drop(['one'], axis=1)
Out[212]: 
      three       two
a       NaN -0.351587
b -0.177289  1.136249
c  0.462215 -0.448789
d  1.124472 -1.101558

注意下面的也可以,但是不太明显/干净:

In [213]: df.reindex(df.index.difference(['a', 'd']))
Out[213]: 
        one     three       two
b -0.138894 -0.177289  1.136249
c  0.011617  0.462215 -0.448789

Renaming / mapping labels

rename()方法允许您根据某些映射(字典或系列)或任意函数重新标记轴。

In [214]: s
Out[214]: 
a   -0.365106
b    1.092702
c   -1.481449
d    1.781190
e   -0.031543
dtype: float64

In [215]: s.rename(str.upper)
Out[215]: 
A   -0.365106
B    1.092702
C   -1.481449
D    1.781190
E   -0.031543
dtype: float64

如果传递一个函数,它必须在使用任何标签调用时返回一个值(并且必须生成一组唯一值)。也可以使用dict或系列:

In [216]: df.rename(columns={'one' : 'foo', 'two' : 'bar'},
   .....:           index={'a' : 'apple', 'b' : 'banana', 'd' : 'durian'})
   .....: 
Out[216]: 
             foo     three       bar
apple  -0.626544       NaN -0.351587
banana -0.138894 -0.177289  1.136249
c       0.011617  0.462215 -0.448789
durian       NaN  1.124472 -1.101558

如果映射不包括列/索引标签,则不会重命名。此外,映射中的额外标签不会抛出错误。

rename()方法还提供了一个inplace命名参数,默认为False并复制基础数据。传递inplace=True可重新命名数据。

版本0.18.0中的新功能。

最后,rename()也接受一个标量或列表,用于更改Series.name属性。

In [217]: s.rename("scalar-name")
Out[217]: 
a   -0.365106
b    1.092702
c   -1.481449
d    1.781190
e   -0.031543
Name: scalar-name, dtype: float64

Panel类具有相关的rename_axis()类,可以重命名其三个轴中的任何一个。

Iteration

对pandas对象基本迭代的行为取决于类型。当对一个Series迭代时,它被认为是数组类,并且基本迭代产生值。其他数据结构,如DataFrame和Panel,遵循类似于对象的“键”的迭代惯例。

简而言之,基本迭代(for i in object)会产生:

  • Series:值
  • DataFrame:列标签
  • 面板:项目标签

因此,例如,对DataFrame进行迭代可以得到列名:

In [218]: df = pd.DataFrame({'col1' : np.random.randn(3), 'col2' : np.random.randn(3)},
   .....:                   index=['a', 'b', 'c'])
   .....: 

In [219]: for col in df:
   .....:     print(col)
   .....: 
col1
col2

Pandas对象也有像dict一样的iteritems()方法来遍历(key,value)对。

要遍历DataFrame的行,可以使用以下方法:

  • iterrows():将DataFrame的行迭代为(index,Series)对。这将行转换为Series对象,这可以更改dtypes并具有一些性能影响。
  • itertuples():将DataFrame的行迭代为值的namedtuples。这比iterrows()快得多,在大多数情况下,最好使用它来遍历DataFrame的值。

警告

通过pandas对象进行迭代通常是在许多情况下,不需要对行进行手动迭代,可以使用以下方法之一来避免:

  • 查找向量化解决方案:许多操作可以使用内置方法或numpy函数执行,(布尔)索引,...
  • 当你有一个功能不能一次应用在整个DataFrame /系列,最好使用apply()而不是对所有值进行迭代。请参阅function application上的文档。
  • 如果你需要对值进行迭代操作,但性能很重要,可以考虑使用例如。 cython或numba。有关此方法的一些示例,请参见enhancing performance部分。

警告

您应该不要修改您要迭代的内容。这不能保证在所有情况下都可用。根据数据类型,迭代器返回一个副本而不是一个视图,并且写入它将没有效果!

例如,在以下情况下,设置值不起作用:

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

In [221]: for index, row in df.iterrows():
   .....:     row['a'] = 10
   .....: 

In [222]: df
Out[222]: 
   a  b
0  1  a
1  2  b
2  3  c

iteritems

与dict类似接口一致,iteritems()通过键值对进行迭代:

  • 系列:(索引,标量值)对
  • DataFrame:(列,系列)对
  • 面板:(item,DataFrame)对

例如:

In [223]: for item, frame in wp.iteritems():
   .....:     print(item)
   .....:     print(frame)
   .....: 
Item1
                   A         B         C         D
2000-01-01 -1.032011  0.969818 -0.962723  1.382083
2000-01-02 -0.938794  0.669142 -0.433567 -0.273610
2000-01-03  0.680433 -0.308450 -0.276099 -1.821168
2000-01-04 -1.993606 -1.927385 -2.027924  1.624972
2000-01-05  0.551135  3.059267  0.455264 -0.030740
Item2
                   A         B         C         D
2000-01-01  0.935716  1.061192 -2.107852  0.199905
2000-01-02  0.323586 -0.641630 -0.587514  0.053897
2000-01-03  0.194889 -0.381994  0.318587  2.089075
2000-01-04 -0.728293 -0.090255 -0.748199  1.318931
2000-01-05 -2.029766  0.792652  0.461007 -0.542749

iterrows

iterrows()允许您将DataFrame的行作为Series对象进行迭代。它返回一个迭代器,产生每个索引值以及包含每行中数据的Series:

In [224]: for row_index, row in df.iterrows():
   .....:     print('%s\n%s' % (row_index, row))
   .....: 
0
a    1
b    a
Name: 0, dtype: object
1
a    2
b    b
Name: 1, dtype: object
2
a    3
b    c
Name: 2, dtype: object

注意

因为iterrows()为每一行返回一个Series,所以它保留跨行的Dtypes(对于DataFrames,Dtypes保留在列之间)。例如,

In [225]: df_orig = pd.DataFrame([[1, 1.5]], columns=['int', 'float'])

In [226]: df_orig.dtypes
Out[226]: 
int        int64
float    float64
dtype: object

In [227]: row = next(df_orig.iterrows())[1]

In [228]: row
Out[228]: 
int      1.0
float    1.5
Name: 0, dtype: float64

以系列形式返回的row中的所有值现在都转换为浮动,也是列x中的原始整数值:

In [229]: row['int'].dtype
Out[229]: dtype('float64')

In [230]: df_orig['int'].dtype
Out[230]: dtype('int64')

要在遍历行时保留dtypes,最好使用itertuples(),它返回值的namedtuples,通常比iterrows快得多。

例如,一个设计的方式来转置DataFrame将是:

In [231]: df2 = pd.DataFrame({'x': [1, 2, 3], 'y': [4, 5, 6]})

In [232]: print(df2)
   x  y
0  1  4
1  2  5
2  3  6

In [233]: print(df2.T)
   0  1  2
x  1  2  3
y  4  5  6

In [234]: df2_t = pd.DataFrame(dict((idx,values) for idx, values in df2.iterrows()))

In [235]: print(df2_t)
   0  1  2
x  1  2  3
y  4  5  6

itertuples

itertuples()方法将返回一个迭代器,为DataFrame中的每一行生成一个namedtuple。元组的第一个元素将是行的对应索引值,而剩余的值是行值。

例如,

In [236]: for row in df.itertuples():
   .....:     print(row)
   .....: 
Pandas(Index=0, a=1, b='a')
Pandas(Index=1, a=2, b='b')
Pandas(Index=2, a=3, b='c')

此方法不会将该行转换为Series对象,而只返回namedtuple中的值。因此,itertuples()保留值的数据类型,通常比iterrows()更快。

注意

如果列名称是无效的Python标识符,重复,或以下划线开头,则列名称将重命名为位置名称。在大量列(> 255)的情况下,返回常规元组。

.dt accessor

Series具有访问器,以简洁地返回类似于系列的的datetime属性,如果它是类似于系列的日期时间/期间。这将返回一个系列,索引像现有的系列。

# datetime
In [237]: s = pd.Series(pd.date_range('20130101 09:10:12', periods=4))

In [238]: s
Out[238]: 
0   2013-01-01 09:10:12
1   2013-01-02 09:10:12
2   2013-01-03 09:10:12
3   2013-01-04 09:10:12
dtype: datetime64[ns]

In [239]: s.dt.hour
Out[239]: 
0    9
1    9
2    9
3    9
dtype: int64

In [240]: s.dt.second
Out[240]: 
0    12
1    12
2    12
3    12
dtype: int64

In [241]: s.dt.day
Out[241]: 
0    1
1    2
2    3
3    4
dtype: int64

这使得很好的表达式像这样:

In [242]: s[s.dt.day==2]
Out[242]: 
1   2013-01-02 09:10:12
dtype: datetime64[ns]

你可以使用tz_localize轻松转换时区

In [243]: stz = s.dt.tz_localize('US/Eastern')

In [244]: stz
Out[244]: 
0   2013-01-01 09:10:12-05:00
1   2013-01-02 09:10:12-05:00
2   2013-01-03 09:10:12-05:00
3   2013-01-04 09:10:12-05:00
dtype: datetime64[ns, US/Eastern]

In [245]: stz.dt.tz
Out[245]: <DstTzInfo 'US/Eastern' LMT-1 day, 19:04:00 STD>

您还可以链接这些类型的操作:

In [246]: s.dt.tz_localize('UTC').dt.tz_convert('US/Eastern')
Out[246]: 
0   2013-01-01 04:10:12-05:00
1   2013-01-02 04:10:12-05:00
2   2013-01-03 04:10:12-05:00
3   2013-01-04 04:10:12-05:00
dtype: datetime64[ns, US/Eastern]

您还可以将datetime值格式化为字符串Series.dt.strftime(),该格式支持与标准strftime()相同的格式。

# DatetimeIndex
In [247]: s = pd.Series(pd.date_range('20130101', periods=4))

In [248]: s
Out[248]: 
0   2013-01-01
1   2013-01-02
2   2013-01-03
3   2013-01-04
dtype: datetime64[ns]

In [249]: s.dt.strftime('%Y/%m/%d')
Out[249]: 
0    2013/01/01
1    2013/01/02
2    2013/01/03
3    2013/01/04
dtype: object
# PeriodIndex
In [250]: s = pd.Series(pd.period_range('20130101', periods=4))

In [251]: s
Out[251]: 
0   2013-01-01
1   2013-01-02
2   2013-01-03
3   2013-01-04
dtype: object

In [252]: s.dt.strftime('%Y/%m/%d')
Out[252]: 
0    2013/01/01
1    2013/01/02
2    2013/01/03
3    2013/01/04
dtype: object

.dt存取器适用于period和timedelta类型。

# period
In [253]: s = pd.Series(pd.period_range('20130101', periods=4, freq='D'))

In [254]: s
Out[254]: 
0   2013-01-01
1   2013-01-02
2   2013-01-03
3   2013-01-04
dtype: object

In [255]: s.dt.year
Out[255]: 
0    2013
1    2013
2    2013
3    2013
dtype: int64

In [256]: s.dt.day
Out[256]: 
0    1
1    2
2    3
3    4
dtype: int64
# timedelta
In [257]: s = pd.Series(pd.timedelta_range('1 day 00:00:05', periods=4, freq='s'))

In [258]: s
Out[258]: 
0   1 days 00:00:05
1   1 days 00:00:06
2   1 days 00:00:07
3   1 days 00:00:08
dtype: timedelta64[ns]

In [259]: s.dt.days
Out[259]: 
0    1
1    1
2    1
3    1
dtype: int64

In [260]: s.dt.seconds
Out[260]: 
0    5
1    6
2    7
3    8
dtype: int64

In [261]: s.dt.components
Out[261]: 
   days  hours  minutes  seconds  milliseconds  microseconds  nanoseconds
0     1      0        0        5             0             0            0
1     1      0        0        6             0             0            0
2     1      0        0        7             0             0            0
3     1      0        0        8             0             0            0

注意

Series.dt如果您使用非datetimelike值访问,则会引发TypeError

Vectorized string methods

系列配备了一组字符串处理方法,使其易于对数组的每个元素进行操作。也许最重要的是,这些方法自动排除丢失/ NA值。这些通过系列的str属性访问,通常具有与等效(标量)内置字符串方法匹配的名称。例如:

In [262]: s = pd.Series(['A', 'B', 'C', 'Aaba', 'Baca', np.nan, 'CABA', 'dog', 'cat'])

In [263]: s.str.lower()
Out[263]: 
0       a
1       b
2       c
3    aaba
4    baca
5     NaN
6    caba
7     dog
8     cat
dtype: object

还提供了强大的模式匹配方法,但请注意,模式匹配通常默认使用正则表达式(在某些情况下总是使用它们)。

有关完整的说明,请参阅Vectorized String Methods

Sorting

警告

排序API在0.17.0中基本上改变,对于这些改变,参见here特别地,默认情况下,所有排序方法都返回一个新对象,并且DO NOT就地运行(除非传递inplace=True)。

您可能感兴趣的有两种显而易见的排序:按标签排序和按实际值排序。

By Index

排序轴标签(索引)的主要方法是Series.sort_index()DataFrame.sort_index()方法。

In [264]: unsorted_df = df.reindex(index=['a', 'd', 'c', 'b'],
   .....:                          columns=['three', 'two', 'one'])
   .....: 

# DataFrame
In [265]: unsorted_df.sort_index()
Out[265]: 
   three  two  one
a    NaN  NaN  NaN
b    NaN  NaN  NaN
c    NaN  NaN  NaN
d    NaN  NaN  NaN

In [266]: unsorted_df.sort_index(ascending=False)
Out[266]: 
   three  two  one
d    NaN  NaN  NaN
c    NaN  NaN  NaN
b    NaN  NaN  NaN
a    NaN  NaN  NaN

In [267]: unsorted_df.sort_index(axis=1)
Out[267]: 
   one  three  two
a  NaN    NaN  NaN
d  NaN    NaN  NaN
c  NaN    NaN  NaN
b  NaN    NaN  NaN

# Series
In [268]: unsorted_df['three'].sort_index()
Out[268]: 
a   NaN
b   NaN
c   NaN
d   NaN
Name: three, dtype: float64

By Values

Series.sort_values()DataFrame.sort_values()value排序的入口点(即列或行中的值)。DataFrame.sort_values()可以为axis=0接受可选的by参数,它将使用任意向量或DataFrame的列名称确定排序顺序:

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

In [270]: df1.sort_values(by='two')
Out[270]: 
   one  three  two
0    2      5    1
2    1      3    2
1    1      4    3
3    1      2    4

by参数可以获取列名称列表,例如:

In [271]: df1[['one', 'two', 'three']].sort_values(by=['one','two'])
Out[271]: 
   one  two  three
2    1    2      3
1    1    3      4
3    1    4      2
0    2    1      5

这些方法通过na_position参数对NA值进行了特殊处理:

In [272]: s[2] = np.nan

In [273]: s.sort_values()
Out[273]: 
0       A
3    Aaba
1       B
4    Baca
6    CABA
8     cat
7     dog
2     NaN
5     NaN
dtype: object

In [274]: s.sort_values(na_position='first')
Out[274]: 
2     NaN
5     NaN
0       A
3    Aaba
1       B
4    Baca
6    CABA
8     cat
7     dog
dtype: object

searchsorted

Series具有searchsorted()方法,其工作方式类似于numpy.ndarray.searchsorted()

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

In [276]: ser.searchsorted([0, 3])
Out[276]: array([0, 2])

In [277]: ser.searchsorted([0, 4])
Out[277]: array([0, 3])

In [278]: ser.searchsorted([1, 3], side='right')
Out[278]: array([1, 3])

In [279]: ser.searchsorted([1, 3], side='left')
Out[279]: array([0, 2])

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

In [281]: ser.searchsorted([0, 3], sorter=np.argsort(ser))
Out[281]: array([0, 2])

smallest / largest values

版本0.14.0中的新功能。

Series具有返回最小或最大的n值的nsmallest()nlargest()对于大的Series,这可以比排序整个系列并在结果上调用head(n)更快。

In [282]: s = pd.Series(np.random.permutation(10))

In [283]: s
Out[283]: 
0    9
1    8
2    5
3    3
4    6
5    7
6    0
7    2
8    4
9    1
dtype: int64

In [284]: s.sort_values()
Out[284]: 
6    0
9    1
7    2
3    3
8    4
2    5
4    6
5    7
1    8
0    9
dtype: int64

In [285]: s.nsmallest(3)
Out[285]: 
6    0
9    1
7    2
dtype: int64

In [286]: s.nlargest(3)
Out[286]: 
0    9
1    8
5    7
dtype: int64

版本0.17.0中的新功能。

DataFrame也具有nlargestnsmallest方法。

In [287]: df = pd.DataFrame({'a': [-2, -1, 1, 10, 8, 11, -1],
   .....:                    'b': list('abdceff'),
   .....:                    'c': [1.0, 2.0, 4.0, 3.2, np.nan, 3.0, 4.0]})
   .....: 

In [288]: df.nlargest(3, 'a')
Out[288]: 
    a  b    c
5  11  f  3.0
3  10  c  3.2
4   8  e  NaN

In [289]: df.nlargest(5, ['a', 'c'])
Out[289]: 
    a  b    c
5  11  f  3.0
3  10  c  3.2
4   8  e  NaN
2   1  d  4.0
1  -1  b  2.0
6  -1  f  4.0

In [290]: df.nsmallest(3, 'a')
Out[290]: 
   a  b    c
0 -2  a  1.0
1 -1  b  2.0
6 -1  f  4.0
1 -1  b  2.0
6 -1  f  4.0

In [291]: df.nsmallest(5, ['a', 'c'])
Out[291]: 
   a  b    c
0 -2  a  1.0
1 -1  b  2.0
6 -1  f  4.0
1 -1  b  2.0
6 -1  f  4.0
2  1  d  4.0
4  8  e  NaN

Sorting by a multi-index column

当列为多索引时,必须明确排序,并且通过完全指定by

In [292]: df1.columns = pd.MultiIndex.from_tuples([('a','one'),('a','two'),('b','three')])

In [293]: df1.sort_values(by=('a','two'))
Out[293]: 
    a         b
  one two three
3   1   2     4
2   1   3     2
1   1   4     3
0   2   5     1

Copying

pandas对象上的copy()方法复制基础数据(虽然不是轴索引,因为它们是不可变的),并返回一个新对象。请注意,很少需要复制对象例如,只有很少的方法来改变DataFrame 就地

  • 插入,删除或修改列
  • 分配到indexcolumns属性
  • 对于同质数据,通过values属性或高级索引直接修改值

要清楚,pandas方法一般不对原始对象进行修改;几乎所有的方法都返回新的对象,保持原来的对象不变。如果数据被修改,那是因为你明确这样做了。

dtypes

The main types stored in pandas objects are float, int, bool, datetime64[ns] and datetime64[ns, tz] (in >= 0.17.0), timedelta[ns], category (in >= 0.15.0), and object. 此外,这些类型具有项目大小,例如int64int32有关datetime64 [ns, tz] dtypes的更多详细信息,请参见Series with TZ

DataFrames的一个方便的dtypes属性返回具有每列数据类型的Series。

In [294]: dft = pd.DataFrame(dict(A = np.random.rand(3),
   .....:                         B = 1,
   .....:                         C = 'foo',
   .....:                         D = pd.Timestamp('20010102'),
   .....:                         E = pd.Series([1.0]*3).astype('float32'),
   .....:                                     F = False,
   .....:                                     G = pd.Series([1]*3,dtype='int8')))
   .....: 

In [295]: dft
Out[295]: 
          A  B    C          D    E      F  G
0  0.954940  1  foo 2001-01-02  1.0  False  1
1  0.318163  1  foo 2001-01-02  1.0  False  1
2  0.985803  1  foo 2001-01-02  1.0  False  1

In [296]: dft.dtypes
Out[296]: 
A           float64
B             int64
C            object
D    datetime64[ns]
E           float32
F              bool
G              int8
dtype: object

Series上使用dtype属性。

In [297]: dft['A'].dtype
Out[297]: dtype('float64')

如果pandas对象包含多个数据类型IN A SINGLE COLUMN,则将选择列的dtype以适应所有数据类型(object是最常见的)。

# these ints are coerced to floats
In [298]: pd.Series([1, 2, 3, 4, 5, 6.])
Out[298]: 
0    1.0
1    2.0
2    3.0
3    4.0
4    5.0
5    6.0
dtype: float64

# string data forces an ``object`` dtype
In [299]: pd.Series([1, 2, 3, 6., 'foo'])
Out[299]: 
0      1
1      2
2      3
3      6
4    foo
dtype: object

方法get_dtype_counts()将返回DataFrame中每种类型的列数:

In [300]: dft.get_dtype_counts()
Out[300]: 
bool              1
datetime64[ns]    1
float32           1
float64           1
int64             1
int8              1
object            1
dtype: int64

数字类型将传播并且可以在DataFrames中共存(从v0.11.0开始)。如果传递一个dtype(直接通过dtype关键字,传递ndarray或传递Series,它将被保留在DataFrame操作。此外,不同的数字类型将NOT组合。下面的例子会给你一个味道。

In [301]: df1 = pd.DataFrame(np.random.randn(8, 1), columns=['A'], dtype='float32')

In [302]: df1
Out[302]: 
          A
0  0.647650
1  0.822993
2  1.778703
3 -1.543048
4 -0.123256
5  2.239740
6 -0.143778
7 -2.885090

In [303]: df1.dtypes
Out[303]: 
A    float32
dtype: object

In [304]: df2 = pd.DataFrame(dict( A = pd.Series(np.random.randn(8), dtype='float16'),
   .....:                         B = pd.Series(np.random.randn(8)),
   .....:                         C = pd.Series(np.array(np.random.randn(8), dtype='uint8')) ))
   .....: 

In [305]: df2
Out[305]: 
          A         B    C
0  0.027588  0.296947    0
1 -1.150391  0.007045  255
2  0.246460  0.707877    1
3 -0.455078  0.950661    0
4 -1.507812  0.087527    0
5 -0.502441 -0.339212    0
6  0.528809 -0.278698    0
7  0.590332  1.775379    0

In [306]: df2.dtypes
Out[306]: 
A    float16
B    float64
C      uint8
dtype: object

defaults

默认整数类型为int64,float类型为平台(32位或64位)的float64REGARDLESS以下都将导致int64 dtypes。

In [307]: pd.DataFrame([1, 2], columns=['a']).dtypes
Out[307]: 
a    int64
dtype: object

In [308]: pd.DataFrame({'a': [1, 2]}).dtypes
Out[308]: 
a    int64
dtype: object

In [309]: pd.DataFrame({'a': 1 }, index=list(range(2))).dtypes
Out[309]: 
a    int64
dtype: object

Numpy,但是会在创建数组时选择平台相关类型。以下WILL会导致32位平台上的int32

In [310]: frame = pd.DataFrame(np.array([1, 2]))

upcasting

当与其他类型组合时,类型可以被向上转换,这意味着它们从当前类型(例如int提升到float

In [311]: df3 = df1.reindex_like(df2).fillna(value=0.0) + df2

In [312]: df3
Out[312]: 
          A         B      C
0  0.675238  0.296947    0.0
1 -0.327398  0.007045  255.0
2  2.025163  0.707877    1.0
3 -1.998126  0.950661    0.0
4 -1.631068  0.087527    0.0
5  1.737299 -0.339212    0.0
6  0.385030 -0.278698    0.0
7 -2.294758  1.775379    0.0

In [313]: df3.dtypes
Out[313]: 
A    float32
B    float64
C    float64
dtype: object

DataFrame上的values属性返回dtypes的低共同分母,表示可以适应所有类型的dtype得到均匀的数字numpy数组。这可能会强制某些向上转换

In [314]: df3.values.dtype
Out[314]: dtype('float64')

astype

您可以使用astype()方法将dtypes从一个显式转换为另一个。这些将默认返回一个副本,即使dtype没有改变(通过copy=False来改变这种行为)。此外,如果astype操作无效,它们将引发异常。

向上转换总是根据numpy规则。如果在操作中涉及两个不同的类型,则更多的一般将被用作操作的结果。

In [315]: df3
Out[315]: 
          A         B      C
0  0.675238  0.296947    0.0
1 -0.327398  0.007045  255.0
2  2.025163  0.707877    1.0
3 -1.998126  0.950661    0.0
4 -1.631068  0.087527    0.0
5  1.737299 -0.339212    0.0
6  0.385030 -0.278698    0.0
7 -2.294758  1.775379    0.0

In [316]: df3.dtypes
Out[316]: 
A    float32
B    float64
C    float64
dtype: object

# conversion of dtypes
In [317]: df3.astype('float32').dtypes
Out[317]: 
A    float32
B    float32
C    float32
dtype: object

使用astype()将列的一个子集转换为指定的类型

In [318]: dft = pd.DataFrame({'a': [1,2,3], 'b': [4,5,6], 'c': [7, 8, 9]})

In [319]: dft[['a','b']] = dft[['a','b']].astype(np.uint8)

In [320]: dft
Out[320]: 
   a  b  c
0  1  4  7
1  2  5  8
2  3  6  9

In [321]: dft.dtypes
Out[321]: 
a    uint8
b    uint8
c    int64
dtype: object

注意

当尝试使用astype()loc()将列子集转换为指定类型时,将发生向上转换。

loc()尝试适合我们分配给当前的dtypes,而[]将从右侧覆盖它们。因此,下面的代码段会产生非预期的结果。

In [322]: dft = pd.DataFrame({'a': [1,2,3], 'b': [4,5,6], 'c': [7, 8, 9]})

In [323]: dft.loc[:, ['a', 'b']].astype(np.uint8).dtypes
Out[323]: 
a    uint8
b    uint8
dtype: object

In [324]: dft.loc[:, ['a', 'b']] = dft.loc[:, ['a', 'b']].astype(np.uint8)

In [325]: dft.dtypes
Out[325]: 
a    int64
b    int64
c    int64
dtype: object

object conversion

pandas提供了各种函数来尝试强制将类型从object dtype转换为其他类型。以下函数可用于一维对象数组或标量:

  • to_numeric()(转换为数字dtypes)

    In [326]: m = ['1.1', 2, 3]
    
    In [327]: pd.to_numeric(m)
    Out[327]: array([ 1.1,  2. ,  3. ])
    
  • to_datetime()(转换为datetime对象)

    In [328]: import datetime
    
    In [329]: m = ['2016-07-09', datetime.datetime(2016, 3, 2)]
    
    In [330]: pd.to_datetime(m)
    Out[330]: DatetimeIndex(['2016-07-09', '2016-03-02'], dtype='datetime64[ns]', freq=None)
    
  • to_timedelta()(转换为timedelta对象)

    In [331]: m = ['5us', pd.Timedelta('1day')]
    
    In [332]: pd.to_timedelta(m)
    Out[332]: TimedeltaIndex(['0 days 00:00:00.000005', '1 days 00:00:00'], dtype='timedelta64[ns]', freq=None)
    

要强制执行转换,我们可以传递errors参数,它指定了pandas应该如何处理无法转换为所需dtype或对象的元素。默认情况下,errors='raise',表示在转换过程中会遇到任何错误。但是,如果errors='coerce',这些错误将被忽略,pandas会将有问题的元素转换为pd.NaT(datetime和timedelta)或np.nan(用于数字)。这可能是有用的,如果你在读取大多数所需的dtype(例如,数字,datetime)的数据,但偶尔有不合格的元素混合,你想表示为丢失:

In [333]: import datetime

In [334]: m = ['apple', datetime.datetime(2016, 3, 2)]

In [335]: pd.to_datetime(m, errors='coerce')
Out[335]: DatetimeIndex(['NaT', '2016-03-02'], dtype='datetime64[ns]', freq=None)

In [336]: m = ['apple', 2, 3]

In [337]: pd.to_numeric(m, errors='coerce')
Out[337]: array([ nan,   2.,   3.])

In [338]: m = ['apple', pd.Timedelta('1day')]

In [339]: pd.to_timedelta(m, errors='coerce')
Out[339]: TimedeltaIndex([NaT, '1 days'], dtype='timedelta64[ns]', freq=None)

errors参数有第三个选项errors='ignore',如果遇到转换为所需数据类型的任何错误,它将简单地返回传入的数据:

In [340]: import datetime

In [341]: m = ['apple', datetime.datetime(2016, 3, 2)]

In [342]: pd.to_datetime(m, errors='ignore')
Out[342]: array(['apple', datetime.datetime(2016, 3, 2, 0, 0)], dtype=object)

In [343]: m = ['apple', 2, 3]

In [344]: pd.to_numeric(m, errors='ignore')
Out[344]: array(['apple', 2, 3], dtype=object)

In [345]: m = ['apple', pd.Timedelta('1day')]

In [346]: pd.to_timedelta(m, errors='ignore')
Out[346]: array(['apple', Timedelta('1 days 00:00:00')], dtype=object)

除了对象转换,to_numeric()提供了另一个参数downcast,它提供了将新(或已经)数字数据下转换为较小的dtype的选项,记忆:

In [347]: m = ['1', 2, 3]

In [348]: pd.to_numeric(m, downcast='integer')   # smallest signed int dtype
Out[348]: array([1, 2, 3], dtype=int8)

In [349]: pd.to_numeric(m, downcast='signed')    # same as 'integer'
Out[349]: array([1, 2, 3], dtype=int8)

In [350]: pd.to_numeric(m, downcast='unsigned')  # smallest unsigned int dtype
Out[350]: array([1, 2, 3], dtype=uint8)

In [351]: pd.to_numeric(m, downcast='float')     # smallest float dtype
Out[351]: array([ 1.,  2.,  3.], dtype=float32)

因为这些方法仅适用于一维数组,列表或标量;它们不能直接用于多维对象,如DataFrames。然而,使用apply(),我们可以有效地“应用”每个列上的函数:

In [352]: import datetime

In [353]: df = pd.DataFrame([['2016-07-09', datetime.datetime(2016, 3, 2)]] * 2, dtype='O')

In [354]: df
Out[354]: 
            0                    1
0  2016-07-09  2016-03-02 00:00:00
1  2016-07-09  2016-03-02 00:00:00

In [355]: df.apply(pd.to_datetime)
Out[355]: 
           0          1
0 2016-07-09 2016-03-02
1 2016-07-09 2016-03-02

In [356]: df = pd.DataFrame([['1.1', 2, 3]] * 2, dtype='O')

In [357]: df
Out[357]: 
     0  1  2
0  1.1  2  3
1  1.1  2  3

In [358]: df.apply(pd.to_numeric)
Out[358]: 
     0  1  2
0  1.1  2  3
1  1.1  2  3

In [359]: df = pd.DataFrame([['5us', pd.Timedelta('1day')]] * 2, dtype='O')

In [360]: df
Out[360]: 
     0                1
0  5us  1 days 00:00:00
1  5us  1 days 00:00:00

In [361]: df.apply(pd.to_timedelta)
Out[361]: 
                0      1
0 00:00:00.000005 1 days
1 00:00:00.000005 1 days

gotchas

integer类型数据上执行选择操作可以轻松地将数据上传到floating在未引入nans(从0.11.0开始)的情况下,输入数据的dtype将被保留。参见integer na gotchas

In [362]: dfi = df3.astype('int32')

In [363]: dfi['E'] = 1

In [364]: dfi
Out[364]: 
   A  B    C  E
0  0  0    0  1
1  0  0  255  1
2  2  0    1  1
3 -1  0    0  1
4 -1  0    0  1
5  1  0    0  1
6  0  0    0  1
7 -2  1    0  1

In [365]: dfi.dtypes
Out[365]: 
A    int32
B    int32
C    int32
E    int64
dtype: object

In [366]: casted = dfi[dfi>0]

In [367]: casted
Out[367]: 
     A    B      C  E
0  NaN  NaN    NaN  1
1  NaN  NaN  255.0  1
2  2.0  NaN    1.0  1
3  NaN  NaN    NaN  1
4  NaN  NaN    NaN  1
5  1.0  NaN    NaN  1
6  NaN  NaN    NaN  1
7  NaN  1.0    NaN  1

In [368]: casted.dtypes
Out[368]: 
A    float64
B    float64
C    float64
E      int64
dtype: object

而float dtypes不变。

In [369]: dfa = df3.copy()

In [370]: dfa['A'] = dfa['A'].astype('float32')

In [371]: dfa.dtypes
Out[371]: 
A    float32
B    float64
C    float64
dtype: object

In [372]: casted = dfa[df2>0]

In [373]: casted
Out[373]: 
          A         B      C
0  0.675238  0.296947    NaN
1       NaN  0.007045  255.0
2  2.025163  0.707877    1.0
3       NaN  0.950661    NaN
4       NaN  0.087527    NaN
5       NaN       NaN    NaN
6  0.385030       NaN    NaN
7 -2.294758  1.775379    NaN

In [374]: casted.dtypes
Out[374]: 
A    float32
B    float64
C    float64
dtype: object

Selecting columns based on dtype

版本0.14.1中的新功能。

select_dtypes()方法基于其dtype实现列的子集。

首先,让我们创建一个具有不同dtypes的DataFrame

In [375]: df = pd.DataFrame({'string': list('abc'),
   .....:                    'int64': list(range(1, 4)),
   .....:                    'uint8': np.arange(3, 6).astype('u1'),
   .....:                    'float64': np.arange(4.0, 7.0),
   .....:                    'bool1': [True, False, True],
   .....:                    'bool2': [False, True, False],
   .....:                    'dates': pd.date_range('now', periods=3).values,
   .....:                    'category': pd.Series(list("ABC")).astype('category')})
   .....: 

In [376]: df['tdeltas'] = df.dates.diff()

In [377]: df['uint64'] = np.arange(3, 6).astype('u8')

In [378]: df['other_dates'] = pd.date_range('20130101', periods=3).values

In [379]: df['tz_aware_dates'] = pd.date_range('20130101', periods=3, tz='US/Eastern')

In [380]: df
Out[380]: 
   bool1  bool2 category                      dates  float64  int64 string  \
0   True  False        A 2016-12-24 18:31:36.297875      4.0      1      a   
1  False   True        B 2016-12-25 18:31:36.297875      5.0      2      b   
2   True  False        C 2016-12-26 18:31:36.297875      6.0      3      c   

   uint8  tdeltas  uint64 other_dates            tz_aware_dates  
0      3      NaT       3  2013-01-01 2013-01-01 00:00:00-05:00  
1      4   1 days       4  2013-01-02 2013-01-02 00:00:00-05:00  
2      5   1 days       5  2013-01-03 2013-01-03 00:00:00-05:00  

和dtypes

In [381]: df.dtypes
Out[381]: 
bool1                                   bool
bool2                                   bool
category                            category
dates                         datetime64[ns]
float64                              float64
int64                                  int64
string                                object
uint8                                  uint8
tdeltas                      timedelta64[ns]
uint64                                uint64
other_dates                   datetime64[ns]
tz_aware_dates    datetime64[ns, US/Eastern]
dtype: object

select_dtypes() has two parameters include and exclude that allow you to say “give me the columns WITH these dtypes” (include) and/or “give the columns WITHOUT these dtypes” (exclude).

例如,要选择bool

In [382]: df.select_dtypes(include=[bool])
Out[382]: 
   bool1  bool2
0   True  False
1  False   True
2   True  False

您还可以在numpy dtype层次结构中传递dtype的名称:

In [383]: df.select_dtypes(include=['bool'])
Out[383]: 
   bool1  bool2
0   True  False
1  False   True
2   True  False

select_dtypes()也适用于通用dtypes。

例如,要选择所有数字和布尔列,同时排除无符号整数

In [384]: df.select_dtypes(include=['number', 'bool'], exclude=['unsignedinteger'])
Out[384]: 
   bool1  bool2  float64  int64  tdeltas
0   True  False      4.0      1      NaT
1  False   True      5.0      2   1 days
2   True  False      6.0      3   1 days

要选择字符串列,必须使用object dtype:

In [385]: df.select_dtypes(include=['object'])
Out[385]: 
  string
0      a
1      b
2      c

要查看像numpy.number这样的通用dtype的所有子类型,您可以定义一个函数,返回子类型的树:

In [386]: def subdtypes(dtype):
   .....:     subs = dtype.__subclasses__()
   .....:     if not subs:
   .....:         return dtype
   .....:     return [dtype, [subdtypes(dt) for dt in subs]]
   .....: 

所有numpy类型都是numpy.generic的子类:

In [387]: subdtypes(np.generic)
Out[387]: 
[numpy.generic,
 [[numpy.number,
   [[numpy.integer,
     [[numpy.signedinteger,
       [numpy.int8,
        numpy.int16,
        numpy.int32,
        numpy.int64,
        numpy.int64,
        numpy.timedelta64]],
      [numpy.unsignedinteger,
       [numpy.uint8,
        numpy.uint16,
        numpy.uint32,
        numpy.uint64,
        numpy.uint64]]]],
    [numpy.inexact,
     [[numpy.floating,
       [numpy.float16, numpy.float32, numpy.float64, numpy.float128]],
      [numpy.complexfloating,
       [numpy.complex64, numpy.complex128, numpy.complex256]]]]]],
  [numpy.flexible,
   [[numpy.character, [numpy.string_, numpy.unicode_]],
    [numpy.void, [numpy.record]]]],
  numpy.bool_,
  numpy.datetime64,
  numpy.object_]]

注意

Pandas还定义类型categorydatetime64 [ns, tz] numpy层次结构,并且不会显示与上述函数。

注意

includeexclude参数必须是非字符串序列。

Scroll To Top