跳至内容
Pandas_note

Pandas_note

前言:对于所有代码,能够看到前面的中文就能写出相关代码。

basic conception

  • pandas: panel data

  • db: database

  • crud: create, read, update, delete

  • core class: Series, DataFrame

  • 导入

    1
    
     import pandas as pd

Series

  • 通过list创建
1
s1 = pd.Series([89,97,94],index=["张三","李四","王五"])
  • 通过字典创建
1
s2 = pd.Series({"张三":89, "李四":97, "王五":94})

DataFrame

  • 通过list创建
1
2
3
4
5
6
7
8
content = [
[1,"小李",3.38,"良"],
[2,"小明",6.38,"优"],
[3,"小红",5.38,"良"],
[4,"小张",1.38,"差"],
]
head = ["序号","姓名","分数","评级"]
df1 = pd.DataFrame(content, column=head)
  • 通过字典创建
1
2
3
4
5
6
7
dic = {
"序号": [1, 2, 3, 4],
"姓名": ["小李", "小明", "小红", "小张"],
"分数": [3.38, 6.38, 5.38, 1.38],
"评级": ["良", "优", "良", "差"],
}
df2 = pd.DataFrame(dic)

csv&excel读写

  • csv读写
1
2
df = pd.read_csv("./train.csv")
df.to_csv("./train_cp.csv")
  • excel读写
1
2
df = pd.read_excel("./train.excel")
df.to_excel("./train_cp.excel")

drop删除

  • 已知创建df:

    dic = { “序号”: [1, 2, 3, 4], “姓名”: [“小李”, “小明”, “小红”, “小张”], “分数”: [3.38, 6.38, 5.38, 1.38], “评级”: [“良”, “优”, “良”, “差”], } df = pd.DataFrame(dic)

  • 对象.drop

1
2
3
4
5
6
7
# axis=1表明维度为列 inplace=True表明修改原变量
df.drop("评级", axis = 1, inplace = True)

# 默认axis = 0表明维度为行 默认inplace=False表明不修改原变量而生成一个新变量
df1 = df.drop(1)

df.drop([0,1,2]) # 删掉 1,2,3行,因为前面没有设置index参数所以默认为int从0开始,具体看 下一个二级标题的开始部分
  • 对象.dropna()
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
df = dp.DataFrame({
"A":[7,8,9],
"B":[7,None,5]
})
#    A   B
# 0  7   7
# 1  8   None
# 2  9   5

df.dropna(inplace=True)
print(df)
#    A   B
# 0  7   7
# 2  9   5
  • 对象.drop_duplicates (注意s: duplicates)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
df = dp.DataFrame({
"A":[7,7,7],
"B":[12,13,5],
"C":[7,7,12],
})
#    A   B   C
# 0  7   12  7
# 1  7   13  7
# 2  7   5   12

# subset 参数
df.drop_duplicates(subset=["A","C"]) # subset:第一个参数 等价于df.drop_duplicates(["A","C"])
#    A   B   C
# 0  7   5   12
df.drop_duplicates(subset=["A"]) # df.drop_duplicates(["A"])
#    A   B   C

# keep 参数
df.drop_duplicates(subset=["A"],keep="first") # 默认为first
#    A   B   C
# 0  7   12  7
df.drop_duplicates(subset=["A"],keep="last")
#    A   B   C
# 0  7   5   12
df.drop_duplicates(subset["A"],keep=False)
#    A   B   C
  • 对象.del
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
df = dp.DataFrame({
"A":[1,2,3],
"B":[4,5,6]
})
# 只能删除某列
del df["A"]
print(df)
#    B
# 0  4
# 1  5
# 2  6

删选/保留/逆向删除

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 创建设定了index的DataFrame
data = {
    'name': ['A', 'B', 'C'],
    'age': [25, 30, 35],
    'score': [88, 92, 90]
}
df = pd.DataFrame(data, index=['r1', 'r2', 'r3']) # 注意此处设定了index;以往默认0开始,如果你从k开始则可以拼接
#        name   age    score
# r1        A    25     88.0
# r2        B    30     92.0
# r3        C    35     90.0
  • 布尔索引:保留符合条件的条目(行,元组)
1
2
3
4
5
# 保留大于等于30岁的,直接中括号干上去
df_older = df[df[age]>=30]
#       name   age   score
# r2       B    30    92.0
# r3       C    35    90.0
  • 选择特定列
1
2
3
4
5
# 保留名字和成绩
df_name_score = df[["name","score"]]
#        name     score
# r2        B      92.0
# r3        C      90.0

定位赋值修改

这是修改数据的最常用、最规范的方法。我们通过一个例子来彻底讲清楚。

创建一个示例

注意我特意把行索引设置得比较复杂,包含字符串和整数,这样能更好地展示 loc 和 iloc 的区别。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import pandas as pd

data = {
    'score': [88, 92, 95, 74],
    'age': [25, 30, 35, 22],
    'city': ['NY', 'LA', 'SF', 'TX']
}
# 创建一个包含字符串和整数的复杂索引
df = pd.DataFrame(data, index=['Alice', 'Bob', 100, 'David'])

print("原始 DataFrame:")
print(df)

使用 .iloc (基于整数位置)

原始 DataFrame:

       score  age city
Alice     88   25   NY
Bob       92   30   LA
100       95   35   SF  <-- 注意这里的行索引名是整数 100
David     74   22   TX

iloc 只认位置,不认名字。行号从上到下是 0, 1, 2, 3… 列号从左到右是 0, 1, 2…

1. 修改单个单元格 df.iloc[行号, 列号]

1
2
3
4
5
6
7
8
# 修改第 0 行、第 0 列(Alice的score)的值为 90
df.iloc[0, 0] = 90

#        score  age city
# Alice     90   25   NY  <-- Changed
# Bob       92   30   LA
# 100       95   35   SF
# David     74   22   TX

2. 修改一整行 df.iloc[行号]

1
2
3
4
5
6
7
8
# 修改第 1 行为100, 31, 'Seoul'
df.iloc[1] = [100, 31, 'Seoul']

#        score  age   city
# Alice     90   25     NY
# Bob      100   31  Seoul  <-- Changed
# 100       95   35     SF
#  David     74   22     TX

3. 修改一整列 df.iloc[:, 列号]

: 代表“所有”。[:, 列号] 的意思就是“所有行,但只选指定的列”。

1
2
3
4
5
6
7
8
# 修改第 2 列(city列)的所有值为 'Unknown'
df.iloc[:, 2] = 'Unknown'

#        score  age     city
# Alice     90   25  Unknown  <-- Changed
# Bob      100   31  Unknown  <-- Changed
# 100       95   35  Unknown  <-- Changed
# David     74   22  Unknown  <-- Changed

4. 修改一个切片(子区域) df.iloc[行号范围, 列号范围]

切片范围是**“左闭右开”**的,和普通 Python 列表一样。例如 0:2 表示第0行和第1行,不包括第2行。

1
2
3
4
5
6
7
8
# 修改第 0, 1 行 和 第 0, 1 列组成的区域,所有值设为 -1
df.iloc[0:2, 0:2] = -1

#        score  age     city
# Alice     -1   -1  Unknown
# Bob       -1   -1  Unknown
# 100       95   35  Unknown
# David     74   22  Unknown

使用 .loc (基于标签名称)

loc 只认行索引名和列名。

原始 DataFrame:

       score  age city
Alice     88   25   NY
Bob       92   30   LA
100       95   35   SF  <-- 注意这里的行索引名是整数 100
David     74   22   TX

1. 修改单个单元格 df.loc[行索引名, 列名]

1
2
3
4
5
6
7
8
# 修改行索引为 'Alice'、列名为 'score' 的值为 89
df.loc['Alice', 'score'] = 89

#        score  age city
# Alice     89   25   NY  <-- Changed
# Bob       92   30   LA
# 100       95   35   SF
# David     74   22   TX

2. 修改一整行 df.loc[行索引名]

1
2
3
4
5
6
7
8
# 修改行索引为 'Bob' 的数据
df.loc['Bob'] = [99, 33, 'Paris'] # 要对应好列个数和列类型

#        score  age   city
# Alice     89   25     NY
# Bob       99   33  Paris  <-- Changed
# 100       95   35     SF
# David     74   22     TX

3. 修改一整列 df.loc[:, 列名]

1
2
3
4
5
6
7
8
# 修改列名为 'age' 的所有值为 0
df.loc[:, 'age'] = 0 # 对应好列类型

#        score  age   city
# Alice     89    0  Paris
# Bob       99    0  Paris
# 100       95    0     SF
# David     74    0     TX

4. 修改一个切片 df.loc[行范围, 列范围]

‼️ 重要区别:loc 的切片是**“左右都闭合”**的!'Alice':'Bob' 表示从 ‘Alice’ 到 ‘Bob’,包括 ‘Alice’ 和 ‘Bob’。

1
2
3
4
5
6
7
8
# 修改从 'Alice' 到 'Bob' 的行,'score' 到 'age' 的列,值设为 -1
df.loc['Alice':'Bob', 'score':'age'] = -1

#        score  age   city
# Alice     -1   -1     NY
# Bob       -1   -1  Paris
# 100       95   35     SF
# David     74   22     TX

‼️ 陷阱与总结

看我们的例子,行索引有一个整数 100。

  • df.loc[100] 会找到行索引名为 100 的那一行 (第三行)。
  • df.iloc[2] 会找到物理位置在第3位的那一行(行号为2),也就是索引名为 100 的那一行。在这个例子里,结果碰巧一样。
  • df.iloc[100] 会报错! 因为 DataFrame 只有4行,没有第101个位置(行号100)。
特性.loc (Location).iloc (Integer Location)
定位方式基于标签 (Label-based)基于整数位置 (Integer-based)
输入类型行/列的名字行/列的数字序号 (从0开始)
切片行为包含结束点 (Inclusive)不包含结束点 (Exclusive)
主要用途当你的索引有实际意义时(如姓名、日期)当你需要按位置选取,或索引混乱/无意义时

最佳实践:为了避免混淆,尽量保持代码意图清晰。如果你想按位置操作,就用 .iloc;如果你想按名称操作,就用 .loc。

最后更新于