2023.1.13 总结来自https://mofanpy.com/tutorials/data-manipulation/pandas/
包括pandas数据结构Series/DataFrame;数据选取分类查询等内容
numpy
,我们发现,numpy
主要用途就是对同一类数据进行处理,可以看成数据矩阵Pandas
主要用于一维二维数据,但用于处理数据的功能也比较多,信息种类也更丰富,特别是你有一些包含字符的表格,Pandas
可以帮你处理分析这些字符型的数据表。Pandas
继承了numpy
所有优点,但比numpy慢点pandas中的数据是什么?
Series核心就是一串类似于列表的序列。Pandas Series 为数据提供了一套索引。
pandas.Series( data, index, dtype, name, copy)
data:一组数据(ndarray 类型)。
index:数据索引标签,如果不指定,默认从 0 开始。
dtype:数据类型,默认会自己判断。
name:设置名称。
copy:拷贝数据,默认为 False。
1. 【列表转换】:列表外套个pd.Series() `
import pandas as pd
l = [11,22,33]
s = pd.Series(l)
print(s)
0 11
1 22
2 33
dtype: int64
他这个pandas
是按照excel
表的习惯来的,一般数据一横行是一个数据,每个列是不同特征
所以这里面其实是三个数据,同一个特征数据,所以是3*1
2. 【index
换索引】:'a’是字符串所以要‘’
s = pd.Series(l,index=['a',1,'c'])
print(s)
a 11
1 22
c 33
dtype: int64
3. 【字典创建】:最常规的创建,也是pandas的特色
s=pd.Series({"a":11,"b":22,'c':33})
s
a 11
b 22
c 33
dtype: int64
4. 转化成list
,Series
print("array:", s.to_numpy())
print("list:", s.values.tolist())
array: [11 22 33]
list: [11, 22, 33]
【5. 访问】:5.1 单独访问 5.2 部分访问
s
0 11
1 22
2 33
dtype: int64
#通过索引访问
s[2]
33
s.at[2]
33
pd.Series(s, index = [0, 2])
0 11
2 33
dtype: int64
6. name
import pandas as pd
sites = {1: "Google", 2: "Runoob", 3: "Wiki"}
myvar = pd.Series(sites, index = [1, 2], name="RUNOOB-Series-TEST" )
print(myvar)
1 Google
2 Runoob
Name: RUNOOB-Series-TEST, dtype: object
pandas.DataFrame( data, index, columns, dtype, copy)
data:一组数据(ndarray、series, map, lists, dict 等类型)。
index:索引值,或者可以称为行标签。
columns:列标签,默认为 RangeIndex (0, 1, 2, …, n) 。
dtype:数据类型。
copy:拷贝数据,默认为 False。
row
,竖的叫column
1. 【从二维list转成Dataframe】
df = pd.DataFrame([
[1,2],
[3,4]
])
df
0 | 1 | |
---|---|---|
0 | 1 | 2 |
1 | 3 | 4 |
key
是列索引,这点和Series有区别,相当于属性;每行习惯看成一条完整的数据df=pd.DataFrame({"col1":[1,3],"col2":[2,4]},index=["a","b"])
df
col1 | col2 | |
---|---|---|
a | 1 | 2 |
b | 3 | 4 |
index
更改了行索引s=pd.DataFrame({"col1":pd.Series([1,2,6]),"col2":pd.Series([3,4])})
s
col1 | col2 | |
---|---|---|
0 | 1 | 3.0 |
1 | 2 | 4.0 |
2 | 6 | NaN |
s=pd.DataFrame({"col1":pd.Series([1,2]),"col2":pd.Series([3,4])},index=["a","b"])
s
col1 | col2 | |
---|---|---|
a | NaN | NaN |
b | NaN | NaN |
:.index.columns
s=pd.DataFrame({"'col1'":pd.Series([1,2]),"'col2'":pd.Series([3,4])})
s
'col1' | 'col2' | |
---|---|---|
0 | 1 | 3 |
1 | 2 | 4 |
s.index=['a','b']
s
'col1' | 'col2' | |
---|---|---|
a | 1 | 3 |
b | 2 | 4 |
*这里我们注意这相当于赋值,所以要用=
s.columns=[1,2]
s
1 | 2 | |
---|---|---|
a | 1 | 3 |
b | 2 | 4 |
df.index
, df.columns
print(s)
#左闭右开
print(s.index, "\n")
print(s.columns)
col1 col2
0 1 3.0
1 2 4.0
2 6 NaN
RangeIndex(start=0, stop=3, step=1)
Index(['col1', 'col2'], dtype='object')
我们的思路主要两种:通过索引选取和通过位置选取
import pandas as pd
import numpy as np
data = np.arange(-12, 12).reshape((6, 4))
df = pd.DataFrame(
data,
index=list("abcdef"),
columns=list("ABCD"))
df
A | B | C | D | |
---|---|---|---|---|
a | -12 | -11 | -10 | -9 |
b | -8 | -7 | -6 | -5 |
c | -4 | -3 | -2 | -1 |
d | 0 | 1 | 2 | 3 |
e | 4 | 5 | 6 | 7 |
f | 8 | 9 | 10 | 11 |
df.A
a -12
b -8
c -4
d 0
e 4
f 8
Name: A, dtype: int32
df["A"]
a -12
b -8
c -4
d 0
e 4
f 8
Name: A, dtype: int32
df["A":"D"]
A | B | C | D |
---|
df[["A","D"]]
A | D | |
---|---|---|
a | -12 | -9 |
b | -8 | -5 |
c | -4 | -1 |
d | 0 | 3 |
e | 4 | 7 |
f | 8 | 11 |
多列选择。我们注意[]
数量:多选时,切片就是单[]
,一个个用索引选的时候,是对两对[]
df["a":"a"]
A | B | C | D | |
---|---|---|---|---|
a | -12 | -11 | -10 | -9 |
df["a":"b"]
A | B | C | D | |
---|---|---|---|---|
a | -12 | -11 | -10 | -9 |
b | -8 | -7 | -6 | -5 |
#两个条件
df["A"]["c"]
-4
.at
的写法( 必须先行后列,否则报错)
df.at["c","A"]
-4
函数.loc
是通过索引名字选取的
[行,列]
Excel
习惯的,所以是闭区间【c:d】,并非切片时左闭右开import pandas as pd
import numpy as np
data = np.arange(-12, 12).reshape((6, 4))
df = pd.DataFrame(
data,
index=list("abcdef"),
columns=list("ABCD"))
df
A | B | C | D | |
---|---|---|---|---|
a | -12 | -11 | -10 | -9 |
b | -8 | -7 | -6 | -5 |
c | -4 | -3 | -2 | -1 |
d | 0 | 1 | 2 | 3 |
e | 4 | 5 | 6 | 7 |
f | 8 | 9 | 10 | 11 |
df.loc["c":"d", "B":"D"]
B | C | D | |
---|---|---|---|
c | -3 | -2 | -1 |
d | 1 | 2 | 3 |
print(df.loc["":"c"])
A B C D
a -12 -11 -10 -9
b -8 -7 -6 -5
c -4 -3 -2 -1
print(df.loc[:,"B":"C"])
B C
a -11 -10
b -7 -6
c -3 -2
d 1 2
e 5 6
f 9 10
#这个是np类型的
data
array([[-12, -11, -10, -9],
[ -8, -7, -6, -5],
[ -4, -3, -2, -1],
[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
print("\ndf:\n", df.iloc[2:3, 1:3])
df:
B C
c -3 -2
print("\ndf:\n", df.iloc[[3, 1], :])
df:
A B C D
d 0 1 2 3
b -8 -7 -6 -5
row_labels = df.index[2:4]
print("row_labels:\n", row_labels)
col_labels = df.columns[[0, 3]]
print("col_labels:\n", col_labels)
print("\ndf:\n", df.loc[row_labels, col_labels])
row_labels:
Index(['c', 'd'], dtype='object')
col_labels:
Index(['A', 'B', 'C'], dtype='object')
df:
A B C
c -4 -3 -2
d 0 1 2
这里我们注意有几个[]
1个【】
,要单独表现几个行或列用两个【】
df
A | B | C | D | |
---|---|---|---|---|
a | -12 | -11 | -10 | -9 |
b | -8 | -7 | -6 | -5 |
c | -4 | -3 | -2 | -1 |
d | 0 | 1 | 2 | 3 |
e | 4 | 5 | 6 | 7 |
f | 8 | 9 | 10 | 11 |
df[df["A"]<0]
A | B | C | D | |
---|---|---|---|---|
a | -12 | -11 | -10 | -9 |
b | -8 | -7 | -6 | -5 |
c | -4 | -3 | -2 | -1 |
df["A"]<0
a True
b True
c True
d False
e False
f False
Name: A, dtype: bool
选在第一行数据不小于 -10 的数据
~
非的意思
print("~:\n", df.loc[:, ~(df.iloc[0] < -10)])
print("\n>=:\n", df.loc[:, df.iloc[0] >= -10])
~:
C D
a -10 -9
b -6 -5
c -2 -1
d 2 3
e 6 7
f 10 11
>=:
C D
a -10 -9
b -6 -5
c -2 -1
d 2 3
e 6 7
f 10 11
将数据记录在数据表时,特别是数据归类比较复杂的情况, 比如年级-班级-学生信息这种层级的记录,我们很可能要使用到合并单元格。 我们把这种模式叫做 Multi-Indexing 多索引。
pd.MultiIndex.from_tuples
index
输入【方法1】:pd.MultiIndex.from_tuples()
前面就是一个列表,然后变成MultiIndex
类
import pandas as pd
tuples = [
# 年级,班级
("one", "1"),
("one", "1"),
("one", "2"), ("one", "2"),
("two", "1"),
("two", "1"),
("two", "2"),
("two", "2"),
]
index = pd.MultiIndex.from_tuples(
tuples, names=["grade", "class"])
index
MultiIndex([('one', '1'),
('one', '1'),
('one', '2'),
('one', '2'),
('two', '1'),
('two', '1'),
('two', '2'),
('two', '2')],
names=['grade', 'class'])
s = pd.Series(
["小米", "小明", # 一年一班
"小命", "小勉", # 一年二班
"小牛", "小鸟", # 二年一班
"小南", "小妮" # 二年二班
],
name="name",
index=index)
s
grade class
one 1 小米
1 小明
2 小命
2 小勉
two 1 小牛
1 小鸟
2 小南
2 小妮
Name: name, dtype: object
【方法2】:pd.MultiIndex.from_product()
这个有些规律 每个年级所在班级学生一样多。如下
import pandas as pd
iterables = [
["one", "two"], # 年级
["1", "1", "2", "2"] # 每个学生所在班级
]
index2 = pd.MultiIndex.from_product(
iterables, names=["grade", "class"])
index2
MultiIndex([('one', '1'),
('one', '1'),
('one', '2'),
('one', '2'),
('two', '1'),
('two', '1'),
('two', '2'),
('two', '2')],
names=['grade', 'class'])
s = pd.Series(
["小米", "小明", # 一年一班
"小命", "小勉", # 一年二班
"小牛", "小鸟", # 二年一班
"小南", "小妮" # 二年二班
],
name="name",
index=index2)
s
grade class
one 1 小米
1 小明
2 小命
2 小勉
two 1 小牛
1 小鸟
2 小南
2 小妮
Name: name, dtype: object
【方法3】pd.MultiIndex.from_frame(df)
:你的索引数据也维护在一张 DataFrame 中.其他一样
df = pd.DataFrame(
[
# 年级,班级
("one", "1"),
("one", "1"),
("one", "2"),
("one", "2"),
("two", "1"),
("two", "1"),
("two", "2"),
("two", "2"),
],
columns=["grade", "class"]
)
index3 = pd.MultiIndex.from_frame(df)
index3
MultiIndex([('one', '1'),
('one', '1'),
('one', '2'),
('one', '2'),
('two', '1'),
('two', '1'),
('two', '2'),
('two', '2')],
names=['grade', 'class'])
刚才都是Series。下面用DataFrame举例
df1 = pd.DataFrame(
{"id": [11,12,13,14,15,16,17,18],
"name":
["小米", "小明", # 一年一班
"小命", "小勉", # 一年二班
"小牛", "小鸟", # 二年一班
"小南", "小妮" # 二年二班
]},
index=index)
df1
id | name | ||
---|---|---|---|
grade | class | ||
one | 1 | 11 | 小米 |
1 | 12 | 小明 | |
2 | 13 | 小命 | |
2 | 14 | 小勉 | |
two | 1 | 15 | 小牛 |
1 | 16 | 小鸟 | |
2 | 17 | 小南 | |
2 | 18 | 小妮 |
df2 = pd.DataFrame(
[[11,12,13,14,15,16,17,18],
["小米", "小明", # 一年一班
"小命", "小勉", # 一年二班
"小牛", "小鸟", # 二年一班
"小南", "小妮" # 二年二班
]],
index=["id", "name"])
df2
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
---|---|---|---|---|---|---|---|---|
id | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
name | 小米 | 小明 | 小命 | 小勉 | 小牛 | 小鸟 | 小南 | 小妮 |
方法一样,其实里面他们是一一对应的,所以用columns引入多重索引就行
df2 = pd.DataFrame(
[[11,12,13,14,15,16,17,18],
["小米", "小明", # 一年一班
"小命", "小勉", # 一年二班
"小牛", "小鸟", # 二年一班
"小南", "小妮" # 二年二班
]],
index=["id", "name"],
columns=index, # 多索引加这
)
df2
grade | one | two | ||||||
---|---|---|---|---|---|---|---|---|
class | 1 | 1 | 2 | 2 | 1 | 1 | 2 | 2 |
id | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
name | 小米 | 小明 | 小命 | 小勉 | 小牛 | 小鸟 | 小南 | 小妮 |
方法:就是用索引,很分类用.loc[]
;。列分类用类似二维数组的方法,每个【】
是一个筛选条件
# 一个条件就是在one里的
df2["one"]
class | 1 | 1 | 2 | 2 |
---|---|---|---|---|
id | 11 | 12 | 13 | 14 |
name | 小米 | 小明 | 小命 | 小勉 |
#两个条件,一个是在one里一个是在1里。特别注意这个1是字符串
df2["one"]["1"]
class | 1 | 1 |
---|---|---|
id | 11 | 12 |
name | 小米 | 小明 |
df4 = pd.DataFrame(
{"id": [11,12,13,14,15,16,17,18],
"name":
["小米", "小明", # 一年一班
"小命", "小勉", # 一年二班
"小牛", "小鸟", # 二年一班
"小南", "小妮" # 二年二班
]},
index=index)
df4
id | name | ||
---|---|---|---|
grade | class | ||
one | 1 | 11 | 小米 |
1 | 12 | 小明 | |
2 | 13 | 小命 | |
2 | 14 | 小勉 | |
two | 1 | 15 | 小牛 |
1 | 16 | 小鸟 | |
2 | 17 | 小南 | |
2 | 18 | 小妮 |
.loc
#用loc
df4.loc["one"].loc["2"]
id | name | |
---|---|---|
class | ||
2 | 13 | 小命 |
2 | 14 | 小勉 |
数据有关键词、每个数据带有特定类别?我们怎样可以快速找到对应的类别,聚类分析?groupby()
核心的功能,自然就是将可以被归纳的数据进行归纳汇总
import pandas as pd
df = pd.DataFrame(
[
("小红", "哈利波特", 80),
("小明", "蜘蛛侠", 72),
("小红", "雷神", 83),
("小红", "蜘蛛侠", 45),
("小明", "超人", 57),
],
columns=("人", "人物", "评价"),
)
df
人 | 人物 | 评价 | |
---|---|---|---|
0 | 小红 | 哈利波特 | 80 |
1 | 小明 | 蜘蛛侠 | 72 |
2 | 小红 | 雷神 | 83 |
3 | 小红 | 蜘蛛侠 | 45 |
4 | 小明 | 超人 | 57 |
# 这就把小名小红分成了两组
grouped = df.groupby("人")
#可以查看分组后的索引
grouped.groups
{'小明': [1, 4], '小红': [0, 2, 3]}
df.iloc[grouped.groups["小红"]]
人 | 人物 | 评价 | |
---|---|---|---|
0 | 小红 | 哈利波特 | 80 |
2 | 小红 | 雷神 | 83 |
3 | 小红 | 蜘蛛侠 | 45 |
grouped.get_group("小红")
人 | 人物 | 评价 | |
---|---|---|---|
0 | 小红 | 哈利波特 | 80 |
2 | 小红 | 雷神 | 83 |
3 | 小红 | 蜘蛛侠 | 45 |
grouped.first()
人物 | 评价 | |
---|---|---|
人 | ||
小明 | 蜘蛛侠 | 72 |
小红 | 哈利波特 | 80 |
grouped.last()
人物 | 评价 | |
---|---|---|
人 | ||
小明 | 超人 | 57 |
小红 | 蜘蛛侠 | 45 |
有时候你想要对组进行循环处理,通过一个循环最所有组统一操作一下。那你需要注意一下这个 grouped 的循环,会带着两个字段做循环。 一个是组名,一个是组数据。
for name, group in grouped:
print("name:", name)
print(group)
name: 小明
人 人物 评价
1 小明 蜘蛛侠 72
4 小明 超人 57
name: 小红
人 人物 评价
0 小红 哈利波特 80
2 小红 雷神 83
3 小红 蜘蛛侠 45
df = pd.DataFrame(
[
("小红", "哈利波特", 80),
("小明", "蜘蛛侠", 72),
("小红", "雷神", 83),
("小红", "雷神", 90),
("小红", "蜘蛛侠", 45),
("小明", "超人", 57),
],
columns=("人", "人物", "评价"),
)
df
人 | 人物 | 评价 | |
---|---|---|---|
0 | 小红 | 哈利波特 | 80 |
1 | 小明 | 蜘蛛侠 | 72 |
2 | 小红 | 雷神 | 83 |
3 | 小红 | 雷神 | 90 |
4 | 小红 | 蜘蛛侠 | 45 |
5 | 小明 | 超人 | 57 |
df.groupby(["人", "人物"]).get_group(("小红", "雷神"))
人 | 人物 | 评价 | |
---|---|---|---|
2 | 小红 | 雷神 | 83 |
3 | 小红 | 雷神 | 90 |
sum
, mean
等操作。【方法1】
import numpy as np
grouped["评价"].agg([np.sum, np.mean, np.std])
sum | mean | std | |
---|---|---|---|
人 | |||
小明 | 129 | 64.500000 | 10.606602 |
小红 | 208 | 69.333333 | 21.126603 |
【方法2】
print(grouped.sum())
print(grouped.mean())
print(grouped.std())
评价
人
小明 129
小红 208
评价
人
小明 64.500000
小红 69.333333
评价
人
小明 10.606602
小红 21.126603
rename
来重新命名。grouped["评价"].agg(
[np.sum, np.mean, np.std]
).rename(columns={
"sum": "合",
"mean": "均值",
"std": "标准差"
})
合 | 均值 | 标准差 | |
---|---|---|---|
人 | |||
小明 | 129 | 64.500000 | 10.606602 |
小红 | 208 | 69.333333 | 21.126603 |