首页
文章
隐私
  • 繁體中文
  • 简体中文
首页
文章
隐私
  • 繁體中文
  • 简体中文

【开发笔记】Pandas 资料分析基础操作

只要谈起资料分析,不少人应该都会同意在 Python 环境下,Pandas 套件可说是快速直觉易用的首选。尤其结合 Numpy 与 Matplotlib 组合来操作资料分析,更是大数据和机器学习过程中不可多得的利器

首先载入 csv 到 dataframe

考虑到之后更动上的方便,建议将变量的设置集中到 Config 类别中。

import pandas as pd

# Config
class Config:
    TRAIN_CSV_FILEPATH = './train.csv'

# 从 csv 载入 DataFrame
config = Config()
df = pd.read_csv(config.TRAIN_CSV_FILEPATH)
print(df.head(10))

列印 dataframe 前 10 行的结果如下

   image_id label  image_width  image_height  is_tma
0         4  HGSC        23785         20008   False
1        66  LGSC        48871         48195   False
2        91  HGSC         3388          3388    True
3       281  LGSC        42309         15545   False
4       286    EC        37204         30020   False
5       431  HGSC        39991         40943   False
6       706  HGSC        75606         25965   False
7       970  HGSC        32131         18935   False
8      1020  HGSC        36585         33751   False
9      1080  HGSC        31336         23200   False

接着查看 dataframe 的基本特征

# 查看 dataframe 的行列数
print(df.shape)

# 列印每一行的名称
print(df.columns)
# Index(['image_id', 'label', 'image_width', 'image_height', 'is_tma'], dtype='object')

# 根据标签内容计算各自的数量
print(df["label"].value_counts())

标签的内容与数量如下

HGSC    222
EC      124
CC       99
LGSC     47
MC       46
Name: label, dtype: int64

另外可以针对特定行去除重复,或是不合法/空值的列

# 去除重复的列
print(df["label"].drop_duplicates())

# 去除不合法/空值的列
print(df["label"].dropna())

# 串起来执行也是可以的
print(df["label"].dropna().drop_duplicates())

留意 iloc 与 loc 的差别

iloc 是根据索引来取值,loc 是基于标签来取值。

# 取索引 2 到 5 之间的列(不包含第五列)
print(df.iloc[2:5])

# 使用 loc 的话要先选取行的标签来建立索引
print(df.set_index("label").loc["HGSC"])

# 留意可以只选取特定行来形成子集,减少数据量加快操作
print(df[["label", "image_width", "image_height"]])

过滤功能真的是 Pandas 的精华

Pandas 以非常直觉的语法来操作过滤数据

# 过滤 label 等于 HGSC 的列
print(df[df["label"]=="HGSC"])

# isin() 过滤列表中符合设置条件的列
print(df[df["image_id"].isin([1252, 1289, 4797, 4827, 6281, 6449, 6843, 7955, 8279, 8280, 8713, 9697, 12222, 12442, 15231])])

# 不等于反之只需要加上 ~ 符号作为前缀
print(df[~df["image_id"].isin([1252, 1289, 4797, 4827, 6281, 6449, 6843, 7955, 8279, 8280, 8713, 9697, 12222, 12442, 15231])])

# 且/或的话,只要加上 & 或是 | 作为操作子
print(df[(df["image_width"]>23785) & (df["image_height"]>48195)])
print(df[(df["image_width"]>23785) | (df["image_height"]>48195)])

# 也可以 query('') 加条件子句来让阅读上更容易
print(df.query("image_width > 23785 & image_height > 48195"))
print(df.query("image_width > 23785 | image_height > 48195"))

图表显示更容易直观理解资料特征

import pandas as pd
import matplotlib.pyplot as plt

# Config
class Config:
    TRAIN_CSV_FILEPATH = './train.csv'

# 从 csv 载入 DataFrame
config = Config()
df = pd.read_csv(config.TRAIN_CSV_FILEPATH)

# 根据 label 计算出各个标签的数量有多少 (value_counts 只能计算一柱,但是会自动降幂排列)
value_counts = df[["label"]].value_counts()

_, axes = plt.subplots(nrows=1, ncols=1, figsize=(10, 15))
# 使用圆饼图显示各标签的比例关系
value_counts.plot.pie(ax=axes[0], autopct='%1.2f%%', ylabel="label")
# 使用长条图显示各标签的数量关系
value_counts.plot.bar(ax=axes[1], ylabel="count", grid=True)
# 使用直方图显示特定行各个值出现的频率
df[["image_width"]].plot.hist(ax=axes[2], grid=True)
df[["image_height"]].plot.hist(ax=axes[3], grid=True)

plt.show()

终场加映散布图显示数据变量的分布方式

import plotly.express as px

# groupby() 可以多个 column 来聚合
# size 会把 row 的数量全算是,不管 row 所对应的值是否合法;count 的话,只会计算合法的值
df = df.groupby(["image_width", "image_height", "label"], as_index=False).size()
fig = px.scatter(df, x="image_width", y="image_height", size="size", color="label", height=600, width=1200)
fig.update_xaxes(range=[1_000, 120_000])
fig.update_yaxes(scaleanchor="x", scaleratio=1, range=[1_000, 60_000])
fig.show()