Python SDK示例:DataFrame

本文为您介绍Python SDK中DataFrame相关的典型场景操作示例。

DataFrame

PyODPS提供了DataFrame API,它提供了类似Pandas的接口,但是能充分利用MaxCompute的计算能力。完整的DataFrame文档请参见DataFrame

假设已经存在三张表,分别是pyodps_ml_100k_movies(电影相关的数据)、pyodps_ml_100k_users(用户相关的数据)和pyodps_ml_100k_ratings(评分有关的数据)。

  1. 首先创建MaxCompute的入口对象。

    import os
    from odps import ODPS
    # 确保 ALIBABA_CLOUD_ACCESS_KEY_ID 环境变量设置为用户 Access Key ID,
    # ALIBABA_CLOUD_ACCESS_KEY_SECRET 环境变量设置为用户 Access Key Secret,
    # 不建议直接使用 Access Key ID / Access Key Secret 字符串
    o = ODPS(
        os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'),
        os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
        project='your-default-project',
        endpoint='your-end-point',
    )
  2. 传入Table对象,创建DataFrame对象users。

    from odps.df import DataFrame
    users = DataFrame(o.get_table('pyodps_ml_100k_users'))
  3. 对DataFrame对象可以执行如下操作:

    • 通过dtypes属性可以查看DataFrame的字段和类型,如下所示。

      users.dtypes
    • 通过head方法,可以获取前N条数据,方便快速预览数据。

      users.head(10)

      返回结果如下。

      -

      user_id

      age

      sex

      occupation

      zip_code

      0

      1

      24

      M

      technician

      85711

      1

      2

      53

      F

      other

      94043

      2

      3

      23

      M

      writer

      32067

      3

      4

      24

      M

      technician

      43537

      4

      5

      33

      F

      other

      15213

      5

      6

      42

      M

      executive

      98101

      6

      7

      57

      M

      administrator

      91344

      7

      8

      36

      M

      administrator

      05201

      8

      9

      29

      M

      student

      01002

      9

      10

      53

      M

      lawyer

      90703

    • 对字段进行筛选。

      • 筛选部分字段。

        users[['user_id', 'age']].head(5)

        返回结果如下。

        -

        user_id

        age

        0

        1

        24

        1

        2

        53

        2

        3

        23

        3

        4

        24

        4

        5

        33

      • 排除个别字段,如下所示。

        >>> users.exclude('zip_code', 'age').head(5)

        返回结果如下。

        -

        user_id

        sex

        occupation

        0

        1

        M

        technician

        1

        2

        F

        other

        2

        3

        M

        writer

        3

        4

        M

        technician

        4

        5

        F

        other

      • 排除掉一些字段的同时,通过计算得到一些新的列。例如,将sexM设置为True,否则设置为False,并将此列取名为sex_bool。如下所示。

        >>> users.select(users.exclude('zip_code', 'sex'), sex_bool=users.sex == 'M').head(5)

        返回结果如下。

        -

        user_id

        age

        occupation

        sex_bool

        0

        1

        24

        technician

        True

        1

        2

        53

        other

        False

        2

        3

        23

        writer

        True

        3

        4

        24

        technician

        True

        4

        5

        33

        other

        False

    • 查询年龄在20~25岁之间的人数,如下所示。

      >>> users.age.between(20, 25).count().rename('count')
      943
    • 查询男女用户的数量。

      >>> users.groupby(users.sex).count()

      返回结果如下。

      -

      sex

      count

      0

      F

      273

      1

      M

      670

    • 将用户按职业划分,从高到底,获取人数最多的前10个职业。

      >>> df = users.groupby('occupation').agg(count=users['occupation'].count())
      >>> df.sort(df['count'], ascending=False)[:10]

      返回结果如下。

      -

      occupation

      count

      0

      student

      196

      1

      other

      105

      2

      educator

      95

      3

      administrator

      79

      4

      engineer

      67

      5

      programmer

      66

      6

      librarian

      51

      7

      writer

      45

      8

      executive

      32

      9

      scientist

      31

      DataFrame API提供了value_counts方法来快速达到同样的目的。

      >>> users.occupation.value_counts()[:10]

      返回结果如下。

      -

      occupation

      count

      0

      student

      196

      1

      other

      105

      2

      educator

      95

      3

      administrator

      79

      4

      engineer

      67

      5

      programmer

      66

      6

      librarian

      51

      7

      writer

      45

      8

      executive

      32

      9

      scientist

      31

    • 使用更直观的图来查看这份数据。

       %matplotlib inline
    • 使用横向的柱状图来可视化。

      users['occupation'].value_counts().plot(kind='barh', x='occupation', ylabel='prefession')
      柱状图
    • 使用直方图来可视化。将年龄分成30组,查看各年龄分布的直方图,如下所示。

      >>> users.age.hist(bins=30, title="Distribution of users' ages", xlabel='age', ylabel='count of users')
      直方图
    • 使用JOIN将三张表进行联合后,保存成一张新的表。

      movies = DataFrame(o.get_table('pyodps_ml_100k_movies'))
      ratings = DataFrame(o.get_table('pyodps_ml_100k_ratings'))
      o.delete_table('pyodps_ml_100k_lens', if_exists=True)
      lens = movies.join(ratings).join(users).persist('pyodps_ml_100k_lens')
      lens.dtypes

      结果如下。

      odps.Schema {
        movie_id                            int64
        title                               string
        release_date                        string
        video_release_date                  string
        imdb_url                            string
        user_id                             int64
        rating                              int64
        unix_timestamp                      int64
        age                                 int64
        sex                                 string
        occupation                          string
        zip_code                            string
      }
    • 把0~79岁的年龄,分成8个年龄段。

      labels = ['0-9', '10-19', '20-29', '30-39', '40-49', '50-59', '60-69', '70-79']
      cut_lens = lens[lens, lens.age.cut(range(0, 80, 10), right=False, labels=labels).rename('年龄分组')]
    • 取分组和年龄唯一的前10条数据来进行查看。

      >>> cut_lens['年龄分组', 'age'].distinct()[:10]

      结果如下。

      -

      年龄分组

      age

      0

      0-9

      7

      1

      10-19

      10

      2

      10-19

      11

      3

      10-19

      13

      4

      10-19

      14

      5

      10-19

      15

      6

      10-19

      16

      7

      10-19

      17

      8

      10-19

      18

      9

      10-19

      19

    • 对各个年龄分组下,用户的评分总数和评分均值进行查看,如下所示。

      cut_lens.groupby('年龄分组').agg(cut_lens.rating.count().rename('评分总数'), cut_lens.rating.mean().rename('评分均值'))

      结果如下。

      -

      年龄分组

      评分均值

      评分总数

      0

      0-9

      3.767442

      43

      1

      10-19

      3.486126

      8181

      2

      20-29

      3.467333

      39535

      3

      30-39

      3.554444

      25696

      4

      40-49

      3.591772

      15021

      5

      50-59

      3.635800

      8704

      6

      60-69

      3.648875

      2623

      7

      70-79

      3.649746

      197