pandas 基本操作

概述

python 的 pandas 库用来处理表格类型(也就是矩阵)的数据非常方便, 这个库用来在可视化之前对数据进行变换,计算和汇总之类的操作再好不过。

下面整理了最近我在做数据分析的短视频时常用的一些方法。

读取数据文件

做视频之前,我采集的数据都是用 csv 格式保存的,这里主要演示 pandas 库的 read_csv 方法。
读取其他文件格式的方式类似,主要是函数名称不同,参数都差不多。

读取 csv 文件

读取 csv 文件非常简单,指定 csv 文件的路径即可。 测试用 csv 文件内容如下:

IP地址,手机号,登录日期
223.104.147.75,19951762925,"2021-04-15 01:33:08"
117.181.52.75,15873565020,"2021-04-15 01:48:24"
42.49.165.99,18673535620,"2021-04-15 02:14:40"
14.116.141.24,18673535620,"2021-04-15 05:01:40"
# -*- coding: utf-8 -*-

import pandas as pd

def test():
    df = pd.read_csv(
        "~/share/test.csv",
    )
    print(df)


if __name__ == "__main__":
    test()

程序运行结果:

$ python test.py
                  IP地址          手机号码                 登录日期
0       223.104.147.75  1.995176e+10  2021-04-15 01:33:08
1        117.181.52.75  1.587357e+10  2021-04-15 01:48:24
2         42.49.165.99  1.867354e+10  2021-04-15 02:14:40
3        14.116.141.24  1.867354e+10  2021-04-15 05:01:40

读取之后修改列的名称,指定列的类型

csv 文件中的列名有时候没有,或者有时候是中文的,列名是后续进行操作数据时使用的 key,一般在读取时将其转换成英文。
同时,可以看出手机号码默认被当成数值类型了,所以用科技计数法来表示,在读取数据时,可以设置此列为字符串类型。

# -*- coding: utf-8 -*-

import pandas as pd

def test():
    df = pd.read_csv(
        "~/share/test.csv",
        skiprows=[0],
        names=["ip", "mobile", "login_date"],
        dtype={"mobile": str},
    )
    print(df)


if __name__ == "__main__":
    test()
  1. skiprows 可以用来忽略第一行标题,因为我们用 names 指定了新的标题名称。
  2. dtype 用来指定某列的类型,不指定的话,系统自动推断类型。

程序运行结果:

$ python test.py
                    ip       mobile           login_date
0       223.104.147.75  19951762925  2021-04-15 01:33:08
1        117.181.52.75  15873565020  2021-04-15 01:48:24
2         42.49.165.99  18673535620  2021-04-15 02:14:40
3        14.116.141.24  18673535620  2021-04-15 05:01:40

列的名称已替换,手机号码也正常显示。

读取 csv 文件的某几列

在分析数据时,有时候我们不需要采集的所有数据,只取其中需要的几列数据。
比如上面的 csv,如果只分析 IP 地址和登录时间,读取文件时,可以只取这 2 列数据。

# -*- coding: utf-8 -*-

import pandas as pd

def test():
    df = pd.read_csv(
        "~/share/test.csv",
        skiprows=[0],
        usecols=[0, 2],
        names=["ip", "login_date"],
    )
    print(df)


if __name__ == "__main__":
    test()

通过 usecols 来指定需要那几列。 程序运行结果:

$ python test.py
                    ip           login_date
0       223.104.147.75  2021-04-15 01:33:08
1        117.181.52.75  2021-04-15 01:48:24
2         42.49.165.99  2021-04-15 02:14:40
3        14.116.141.24  2021-04-15 05:01:40

读取时对某些列进行转换

有些列的格式,比如日期格式的列,可能在分析之前就要进行转换处理。
上面的例子中,如果是按日分析登录情况,就不要时分秒的部分,这样我们可以在读取时就进行转换处理。

# -*- coding: utf-8 -*-
from datetime import datetime

import pandas as pd

def test():
    df = pd.read_csv(
        "~/share/test.csv",
        skiprows=[0],
        usecols=[0, 2],
        names=["ip", "login_date"],
        converters={
            "login_date": lambda d: datetime.strptime(d, "%Y-%m-%d %H:%M:%S").strftime(
                "%Y-%m-%d"
            )
        },
    )
    print(df)


if __name__ == "__main__":
    test()

通过 converters 参数转换某列。 程序运行结果:

$ python test.py
                    ip  login_date
0       223.104.147.75  2021-04-15
1        117.181.52.75  2021-04-15
2         42.49.165.99  2021-04-15
3        14.116.141.24  2021-04-15

数据的操作

读取文件之后,得到一个 dataframe 结构,它可以当成一个矩阵来看。
基于 dataframe,可以完成各种计算操作,pandas 提供的 API 也很多,这里只介绍我平时常用的一部分。

分组统计

之前做房价分析时,按月分析成交平均值和成交总套数时,都用到了分组统计。
分析的第一步就是将数据分组。

# -*- coding: utf-8 -*-

import pandas as pd

test_data = {
    "name": ["a", "b", "c", "d"],
    "value": [11, 20, 31, 42],
    "date": ["2017", "2018", "2018", "2017"],
}


def main():
    df = pd.DataFrame(test_data)
    data = df.groupby("date")
    data = data.sum()
    print(data)


if __name__ == "__main__":
    main()

按照日期分组之后,运行结果如下:

$ python test2.py
      value
date
2017     53
2018     51

这里是求和,groupby 之后同样也可以求平均值。

数据集变换

数据集变换是用的比较多的,因为采集和分析的过程是分开的,采集的目的是数据尽量全和准确。
所以分析之前会根据分析目的会对数据进行适当的变换。

行操作

行操作主要指从数据集中过滤出一部分数据,或者合并多个数据集。

  1. 过滤数据

    # -*- coding: utf-8 -*-
    
    import pandas as pd
    
    test_data = {
        "name": ["a", "b", "c", "d"],
        "value": [11, 20, 31, 42],
        "date": ["2017", "2018", "2018", "2017"],
    }
    
    
    def main():
        df = pd.DataFrame(test_data)
        # 选取2017年的数据
        data2017 = df[df["date"] == "2017"]
        print(data2017)
    
        # 选取value>30 的数据
        data30 = df[df["value"] > 30]
        print(data30)
    
    
    if __name__ == "__main__":
        main()
    

    运行结果如下:

    $ python test2.py
      name  value  date
    0    a     11  2017
    3    d     42  2017
      name  value  date
    2    c     31  2018
    3    d     42  2017
    
    

    可以很方便的直接使用列名来过滤数据行

  2. 合并数据集

    # -*- coding: utf-8 -*-
    
    import pandas as pd
    
    test_data_01 = {
        "name": ["a", "b", "c", "d"],
        "value": [11, 20, 31, 42],
        "date": ["2017", "2018", "2018", "2017"],
    }
    
    test_data_02 = {
        "name": ["a", "b", "c", "d"],
        "value": [31, 40, 51, 72],
        "date": ["2019", "2020", "2020", "2019"],
    }
    
    
    def main():
        df01 = pd.DataFrame(test_data_01)
        df02 = pd.DataFrame(test_data_02)
    
        # 合并数据集时,设置 ignore_index = True,可以避免index重复
        data = pd.concat([df01, df02], ignore_index=True)
        print(data)
    
    
    if __name__ == "__main__":
        main()
    
    

    运行结果如下:

    $ python test2.py
      name  value  date
    0    a     11  2017
    1    b     20  2018
    2    c     31  2018
    3    d     42  2017
    4    a     31  2019
    5    b     40  2020
    6    c     51  2020
    7    d     72  2019
    
    

    如果不设置 ignore_index = True,执行结果如下:(注意第一列有重复)

    $ python test2.py
      name  value  date
    0    a     11  2017
    1    b     20  2018
    2    c     31  2018
    3    d     42  2017
    0    a     31  2019
    1    b     40  2020
    2    c     51  2020
    3    d     72  2019
    
    

列操作

列操作我用到的场景,有一个是横向统计各个列的合计和平均值。
示例如下:

# -*- coding: utf-8 -*-

import pandas as pd

test_data_01 = {
    "a": [11, 20],
    "b": [1, 2],
}


def main():
    df = pd.DataFrame(test_data_01)

    df["a+b"] = df["a"] + df["b"]
    df["(a+b)/2"] = (df["a"] + df["b"]) / 2
    print(df)


if __name__ == "__main__":
    main()

运行结果如下:

$ python test2.py
    a  b  a+b  (a+b)/2
0  11  1   12      6.0
1  20  2   22     11.0

还有就是进行数据集的列合并,比如将多个数据集的统计结果进行合并:

# -*- coding: utf-8 -*-

import pandas as pd

test_data_01 = {
    "a": [11, 20],
    "b": [1, 2],
}

test_data_02 = {
    "c": [18, 50],
    "d": [31, 32],
}


def main():
    df01 = pd.DataFrame(test_data_01)
    df02 = pd.DataFrame(test_data_02)

    df01["a+b"] = df01["a"] + df01["b"]
    df01["(a+b)/2"] = (df01["a"] + df01["b"]) / 2
    df01 = df01.drop(columns=["a", "b"])

    df02["c+d"] = df02["c"] + df02["d"]
    df02["(c+d)/2"] = (df02["c"] + df02["d"]) / 2
    df02 = df02.drop(columns=["c", "d"])

    df = pd.concat([df01, df02], axis=1)
    print(df)


if __name__ == "__main__":
    main()

运行结果如下:

$ python test2.py
   a+b  (a+b)/2  c+d  (c+d)/2
0   12      6.0   49     24.5
1   22     11.0   82     41.0

行列互换

行列互换我一般是在做动态短视频时使用的,把每个时间点一行数据(数据包含各个元素),变成每个元素在每个时间点一个数据。

开始时,数据类似:

date,a,b
2017,1,2
2018,2,3

转换后变成:

key,date,value
a,2017,1
a,2018,2
b,2017,2
b,2018,3

转换代码:

# -*- coding: utf-8 -*-

import pandas as pd

test_data = {
    "date": ["2017", "2018"],
    "a": [1, 2],
    "b": [2, 3],
}


def main():
    df = pd.DataFrame(test_data)
    print("转换前:>>>>>>")
    print(df)

    data = df.drop(columns=["date"])
    data = pd.melt(data)

    df_date = pd.concat([df["date"]] * 2, ignore_index=True)
    data = pd.concat([df_date, data], axis=1)
    print("\n转换后:>>>>>>")
    print(data)


if __name__ == "__main__":
    main()

运行结果如下:

$ python test2.py
转换前:>>>>>>
   date  a  b
0  2017  1  2
1  2018  2  3

转换后:>>>>>>
   date variable  value
0  2017        a      1
1  2018        a      2
2  2017        b      2
3  2018        b      3

导出数据文件

导出文件很简单,只要指定个路径即可(注意,路径不存在会报错)。

data.to_csv("./test.csv")

导出时,如果不想导出每行数据的序号,加上 index=False

data.to_csv("./test.csv", index=False)

如果给标题行重新命名成易懂的中文名称,设置 header 参数。

data.to_csv(
    "./test.csv",
    index=False,
    header=[
        "日期",
        "名称",
        "时间(小时)",
    ],
)

总结

掌握了 pandas,感觉是多了一件随便操作数据集的利器,能够极大节省调整数据的时间。
而且,它的处理速度极快,我在自己的笔记本电脑上处理成千上万条数据时基本都是瞬间完成,同样的数据,我用 excel 来处理,会卡顿很多。

我的视频号:
databook 视频号

posted @ 2021-04-26 22:06  wang_yb  阅读(312)  评论(0编辑  收藏  举报