Pandas 中文官档~基础用法5

.dt 访问器

Series 提供了一个可以简单、快捷返回 datetime 属性值的访问器。这个访问器返回的也是 Series,索引与现有的 Series 一样。

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

In [265]: s
Out[265]: 
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 [266]: s.dt.hour
Out[266]: 
0    9
1    9
2    9
3    9
dtype: int64

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

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

用下列表达式进行筛选非常方便:

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

还可以轻易实现时区转换:

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

In [271]: stz
Out[271]: 
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 [272]: stz.dt.tz
Out[272]: <DstTzInfo 'US/Eastern' LMT-1 day, 19:04:00 STD>

还可以把这些操作连在一起:

In [273]: s.dt.tz_localize('UTC').dt.tz_convert('US/Eastern')
Out[273]: 
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]

还可以用 Series.dt.strftime()datetime 的值当成字符串进行格式化,支持与标准的 strftime() 同样的格式。

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

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

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

In [278]: s
Out[278]: 
0    2013-01-01
1    2013-01-02
2    2013-01-03
3    2013-01-04
dtype: period[D]

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

.dt 访问器还支持 periodtimedelta

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

In [281]: s
Out[281]: 
0    2013-01-01
1    2013-01-02
2    2013-01-03
3    2013-01-04
dtype: period[D]

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

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

In [285]: s
Out[285]: 
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 [286]: s.dt.days
Out[286]: 
0    1
1    1
2    1
3    1
dtype: int64

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

In [288]: s.dt.components
Out[288]: 
   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

::: tip 注意

用这个访问器处理不是 datetime 类型的值时,Series.dt 会触发 TypeError 错误。

:::

矢量化字符串方法

Series 支持字符串处理方法,操作数组中每个元素十分方便。这些方法会自动排除缺失值与空值,这也许是其最重要的特性。这些方法通过 Series 的 str 属性访问,一般情况下,这些操作的名称与内置的字符串方法一致。示例如下:

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

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

这里还提供了强大的模式匹配方法,但工业注意,模式匹配方法默认使用正则表达式

参阅矢量化字符串方法了解完整内容。

排序

Pandas 支持三种排序方式,按索引标签排序,按列里的值排序,按两种方式混合排序。

按索引排序

Series.sort_index()DataFrame.sort_index() 方法用于按索引层级对 pandas 对象排序。

In [291]: 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 [292]: unsorted_df = df.reindex(index=['a', 'd', 'c', 'b'],
   .....:                          columns=['three', 'two', 'one'])
   .....: 

In [293]: unsorted_df
Out[293]: 
      three       two       one
a       NaN -1.152244  0.562973
d -0.252916 -0.109597       NaN
c  1.273388 -0.167123  0.640382
b -0.098217  0.009797 -1.299504

# DataFrame
In [294]: unsorted_df.sort_index()
Out[294]: 
      three       two       one
a       NaN -1.152244  0.562973
b -0.098217  0.009797 -1.299504
c  1.273388 -0.167123  0.640382
d -0.252916 -0.109597       NaN

In [295]: unsorted_df.sort_index(ascending=False)
Out[295]: 
      three       two       one
d -0.252916 -0.109597       NaN
c  1.273388 -0.167123  0.640382
b -0.098217  0.009797 -1.299504
a       NaN -1.152244  0.562973

In [296]: unsorted_df.sort_index(axis=1)
Out[296]: 
        one     three       two
a  0.562973       NaN -1.152244
d       NaN -0.252916 -0.109597
c  0.640382  1.273388 -0.167123
b -1.299504 -0.098217  0.009797

# Series
In [297]: unsorted_df['three'].sort_index()
Out[297]: 
a         NaN
b   -0.098217
c    1.273388
d   -0.252916
Name: three, dtype: float64

按值排序

Series.sort_values() 方法用于按值对 Series 排序。DataFrame.sort_values() 方法用于按行列的值对 DataFrame 排序。DataFrame.sort_values() 的可选参数 by 用于指定按哪列排序,该参数的值可以是一列或多列数据。

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

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

参数 by 支持列名列表,示例如下:

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

这些方法支持用 na_position 参数处理空值。

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

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

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

按索引与值排序

0.23.0 版新增

通过参数 by 传递给 DataFrame.sort_values() 的字符串可以引用列或索引层名。

# 创建 MultiIndex
In [304]: idx = pd.MultiIndex.from_tuples([('a', 1), ('a', 2), ('a', 2),
   .....:                                 ('b', 2), ('b', 1), ('b', 1)])
   .....: 

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

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

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

second(索引)与 A(列)排序。

In [308]: df_multi.sort_values(by=['second', 'A'])
Out[308]: 
              A
first second   
b     1       1
      1       2
a     1       6
b     2       3
a     2       4
      2       5

::: tip 注意

如果字符串、列名、索引层名重名,会触发警告提示,并以列名为准。后期版本中,这种情况将会触发模糊错误。

:::

搜索排序

Series 支持 searchsorted() 方法,这与numpy.ndarray.searchsorted() 的操作方式类似。

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

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

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

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

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

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

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

最大值与最小值

Series 支持 nsmallest()nlargest() 方法,本方法返回 N 个最大或最小的值。对于数据量大的 Series 来说,该方法比先为整个 Series 排序,再调用 head(n) 这种方式的速度要快得多。

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

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

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

In [319]: s.nsmallest(3)
Out[319]: 
1    0
4    1
0    2
dtype: int64

In [320]: s.nlargest(3)
Out[320]: 
6    9
8    8
3    7
dtype: int64

DataFrame 也支持 nlargestnsmallest 方法。

In [321]: 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 [322]: df.nlargest(3, 'a')
Out[322]: 
    a  b    c
5  11  f  3.0
3  10  c  3.2
4   8  e  NaN

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

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

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

用多重索引的列排序

列为多重索引时,还可以显式排序,用 by 可以指定所有层级。

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

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

复制

在 pandas 对象上执行 copy() 方法,将复制底层数据(但不包括轴索引,因为轴索引不可变),并返回一个新的对象。注意,复制对象这种操作一般来说不是必须的。比如说,以下几种方式可以就地(inplace) 改变 DataFrame:

  • 插入、删除、修改列
  • indexcolumns 属性赋值
  • 对于同质数据,用 values 属性或高级索引即可直接修改值

注意,用 pandas 方法修改数据不会带来任何副作用,几乎所有方法都返回新的对象,不会修改原始数据对象。如果原始数据有所改动,唯一的可能就是用户显式指定了要修改原始数据。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容