pandas操作集锦

  |  

摘要: 本文记录一下日常的项目中遇到的 pandas 的问题以及解决方案

【对算法,数学,计算机感兴趣的同学,欢迎关注我哈,阅读更多原创文章】
我的网站:潮汐朝夕的生活实验室
我的公众号:算法题刷刷
我的知乎:潮汐朝夕
我的github:FennelDumplings
我的leetcode:FennelDumplings


参考资料:


增删改查

倒序

1
2
3
4
idxs = list(df.index)
reversed_idx = list(reversed(idxs))
df = df.iloc[reversed_idx, :]
df.index = pd.Index(idxs)

删除 Unnamed 列

在操作 DF 时,经常会出现一些 Unnamed 列。如果直接 to_csv,下次 read_csv 之后可以手动删一下再进行后续操作。

1
df = df.loc[:, ~df.columns.str.contains('Unnamed')]

增加一行数据

1
2
s = pd.Series({"key1": val1, "key2": val2})
df = df.append(s, ignore_index=True) # 不使用 index 标签

新增一列并按条件赋值

条件判断的逻辑可以在 func 里面改,如果条件不复杂,可以用 lambda

1
2
3
4
5
6
7
def func(row):
if row.loc[condition_col] <= ...:
return 0
else:
return 1

df[new_col_name] = df.apply(func, axis=1)

字符串列的替换

1
2
3
for index in df1["col"].index:
if isinstance(df1["col"].iloc[index], str):
df1["col"].iloc[index] = df1["col"].iloc[index].replace("新零售/智能汽车", "智能汽车")

新增一列,列数据已有

1
df.insert(loc=1, column="new_col_name", value=np.array(...))

删除一列

以下三种写法都行。把 col_name 改成列名的列表可以删除多列

1
2
3
df = df.drop(col_name, axis=1)
df.drop('col_name', axis=1, inplace=True)
df.drop(df.columns[0], axis=1, inplace=True)

也可以用 del

1
del df[col_name]

修改一列

例如:一个字符串类型的列,将列内所有元素末尾加上一个 “A”

1
2
3
4
def func(s):
return s + "A"

return_df[col_name] = return_df[col_name].apply(func)

随机打乱数据并分成两个集合

1
2
3
4
5
df = df.sample(frac=1.0) # frac 为返回的比例

num_train = int((1 - ratio) * df.shape[0])
train = df.iloc[:num_train]
test = df.iloc[num_train:]

将多个 DF 进行 merge

主键是 col(或者 col 列表),其余字段分布在 3 个表上

1
2
3
4
from functools import reduce

dfs = [df1, df2, df3]
df = reduce(lambda left,right: pd.merge(left, right, on='col', how='left'), dfs)

多表拼接,保留所有行列,某个表没有的列填充 NaN

有若干张df_list 中每个 df 有若干行,

1
df_concated = pd.concat(df_list, axis=0)

按日期筛选数据

取日期在 2018-07-20 到 2018-07-27 之间的数据。

1
2
3
4
5
6
import datetime

s_date = datetime.datetime.strptime("2018-07-20", '%Y-%m-%d')
e_date = datetime.datetime.strptime("2018-07-27", '%Y-%m-%d')
df["date"] = pd.to_datetime(df["date"]) # 把字符型的日期列解析为时间型的序列
df_tmp = df[(df["date"]>=s_date) & (df["date"]<=e_date)]

统计dataframe中某一列数据中每个元素出现的次数

DataFrame 中有一个名称为 target 的列,这是个分类型特征,想知道表中所有取值的个数。

1
2
lst = df["target"].values.tolist()
dict(zip(*np.unique(lst, return_counts=True)))

单元格样式

输出 excel 时对一些单元格加颜色

假设有以下表格:

1
2
columns = [["A", "A", "B", "B", "C"], ["a", "b", "c", "d", "e"]]
df = pd.DataFrame(np.arange(50).reshape(10, 5), columns=columns)

现在要根据列名对列加颜色,列名与颜色的对应如下,效果如下图:

1
2
3
4
color_map = {"A": "#A2DC1C"
,"B": "#00EE77"
,"C": "#6A6A6A"
}

以下代码中的 style_apply 是具体上色的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def style_apply(series, colors, back_ground=""):
"""
:param series: DataFrame 中的一列,类型为 Series
:param colors: 字典, 含义是 {标题: 颜色}
:param back_ground: 背景颜色
"""
print(series)
series_name = series.name[0] # 两级列名中的第一级
a = list()
# 给每个单元格上色
for _ in series:
if series_name in colors:
# colors 中的 key 为需要上色的列名
back_ground = "background-color: {}".format(colors[series_name])
a.append(back_ground)
return a

style_df = df.style.apply(style_apply, colors=color_map)
style_df.to_excel("color.xlsx")

根据条件获取元素所在位置的index(行索引)

1
row_index = df[df["序号"] == 999].index.tolist()[0]

文件IO

设置 chunksize 参数,控制每次迭代数据的大小

1
2
3
4
5
6
7
8
9
i = 0 # 控制输出
chunker = pd.read_csv("train.csv", chunksize=5)
for item in chunker:
# item 是 pandas.core.frame.DataFrame 类型
# 处理 item
i += 1
if i >= 4:
# 超过 4 则认为数据量过大,跳出循环
break

读取文件时指定行列

指定列

1
2
3
df = pd.read_excel("file.xlsx", usecols=[0, 5]) # 指定读取第 1 列和第 6 列
df = pd.read_excel("file.xlsx", usecols=[0]) # 指定读取第 1 列
df = pd.read_excel("file.xlsx", usecols=[0, 12]) # 指定读取第 1 列、第 2 列、第 3 列

指定行

1
df = pd.read_excel("file.xlsx", nrows=1000) # 读取前 1000 行

一个文件中有多个选项卡(工作表)的处理

方法1:用 pd.ExcelFile 中转:

1
2
3
xls = pd.ExcelFile("file.xlsx")
df1 = pd.read_excel(xls, "sheet1")
df2 = pd.read_excel(xls, "sheet2")

方法2:

1
2
pd.read_excel("file.xlsx", sheet_name=0)
pd.read_excel("file.xlsx", sheet_name="sheet1")

创建表

创建空表,有两个列名

1
df = pd.DataFrame(data=None, columns=["col_name1", "col_name2"])

将表格保存为 csv 文件,不带索引列,| 作分隔符

1
df.to_csv(out_path, index=False, sep="|")

Jupyter

在 Jupyter 中显示全部行

在 jupyter 中,显示一个 DataFrame 的时候,默认情况下只会显示很少的行列,多的会用省略号代替。

增加以下设置可以显示全部行列。

1
2
pd.set_option('display.max_rows', None) # 显示全部行
pd.set_option('display.max_columns', None) # 显示全部列

20230118:

修改列顺序

  • 通过列名列表中转
1
2
columns_order = ['date', 'time', 'open', 'high', 'low', 'close', 'volumefrom', 'volumeto']
df = df[columns_order]
  • 先删除再插入
1
2
3
df_time = df.time
df = df.drop('time', axis=1)
df.insert(0,'time', df_time)

Share