数据可视化学习笔记【二】(pandas包)
pandas包的导入:
import pandas as pd
Cpt 1. 数据的索引 & Series、DataFrame数据结构:
pd.Series()
以及 pd.DataFrame()
,注意要大写首字母。
Series数据结构:
使用自带的索引:(则索引值与列表的索引相同,个人感觉相当于使用 enumerate
函数)
data = pd.Series([1, 2, 3, 4])
print("full data set:\n", data)
A = [1, 2, 3, 4]
print("enumerate 实现:")
for i, item in enumerate(A):
print(i, item)
>>>full data set:
0 1
1 2
2 3
3 4
dtype: int64
enumerate 实现:
0 1
1 2
2 3
3 4
自定义索引,则需要加入一个参数:index
表明索引内容,可以随意定义:(我这里甚至反过来定义,都是可以的,不用从0
开始)
data2 = pd.Series([1,2,3,4], index = [4,3,2,1])
print("自定义索引:\n", data2)
>>>自定义索引:
4 1
3 2
2 3
1 4
dtype: int64
若要查看索引,那就 xxx.index
,如果要只查看所有数值:xxx.values
这里的 xxx
是变量名。
DataFrame 数据结构
熟悉 R 语言之后,对 DataFrame 这个数据结构会有一个更好的理解,调用上来说,方法差不多,在 R 语言内,数据与其索引之间用的是 $
符号,在 python 中,用的是 .
这个符号,以 df[index1]
这样形式,在 R 或是 python 中调用都是可以的。
如果输入的是一个字典,字典的值是列表,就会自动形成这样的结构,如果有缺失值,会变成 NaN
。
df = pd.DataFrame([{"个":i, "十":10*i, "百":100*i} for i in range(1,5)])
print("Data.Frame:\n", df)
>>>Data.Frame:
个 十 百
0 1 10 100
1 2 20 200
2 3 30 300
3 4 40 400
print(df["十"], "\n类似R语言中的调用:\n", df.十)
>>> 0 10
1 20
2 30
3 40
Name: 十, dtype: int64
类似R语言中的调用:
0 10
1 20
2 30
3 40
Name: 十, dtype: int64
上例中,输入的是字典,如果直接输入的是一个二维矩阵,会变为以行作为索引(因为输入是由列表嵌套几个行列表从而构成一个矩阵的),若是要设置列,则需要引入 columns
这个形参:
df2 = pd.DataFrame([[1,2,3],[4,5,6]], index = ["A", "B"], columns = ["c1","c2","c3"])
print(df2)
>>> c1 c2 c3
A 1 2 3
B 4 5 6
索引要点:
- 索引只能在第一次存储的时候进行改变,无法像 R 语言一样通过
colnames
等函数进行改变。 - 两个
DataFrame
的索引之间可以求交集、并集、差集等。
Cpt 2. DataFrame 的运算
如果对 DataFrame
进行例如求指数等操作,与 numpy
中的运算操作相同(全部会改变)数据可视化学习笔记(numpy包),处理的时候一般都会带上 numpy
这个包。
判断 DataFrame
中的元素是否为缺失值:isnull
,notnull
,与 R 语言中的 is.na
是类似的这里就不赘述了。最后会得到一个大小相同,但全是 Bool 值的数组。
删除 NaN 列: dropna
,参数:
axis
删除行还是删除列thresh
如果这一行/列有超过thresh
的值,则删除这一行/列fillna
缺失值用别的数填充,一般常用 0 。
Cpt 3. 层级索引
当这个数组的索引是一个元组、或是一个列表的时候,就称之为层级索引。层级索引实际上与机器学习中分类模型的输出形式类似:将信息进行分类以树形图形式存储。
idx = [("one", "en"), ("one", "de"),
("two", "en"), ("two", "de"),
("three", "en"), ("three", "de"),
("four", "en"), ("four", "de"),
("five", "en"), ("five", "de"),]
digits = ["One", "Eins", "Two", "Zwei",
"Three", "Drei", "Four", "Vier",
"Five", "Funf"]
trans = pd.Series(digits, index = idx)
print("trans =\n", trans)
>>> trans =
(one, en) One
(one, de) Eins
(two, en) Two
(two, de) Zwei
(three, en) Three
(three, de) Drei
(four, en) Four
(four, de) Vier
(five, en) Five
(five, de) Funf
dtype: object
# 对数组中的元素进行调用:(同样的,可以切片调用元素)
print("trans[(\"one\", \"en\")]=", trans[("one", "en")])
>>> trans[("one", "en")]= One
之前提到了用树状结构进行输出,需要用到一个叫做 MultiIndex
这个函数:(在这里转换为一个二维决策,别的情况下可能产生更高维的决策)
midx = pd.MultiIndex.from_tuples(idx)
trans = pd.Series(digits, index = midx)
print(trans)
>>> one en One
de Eins
two en Two
de Zwei
three en Three
de Drei
four en Four
de Vier
five en Five
de Funf
dtype: object
数据结构的转换:
DataFrame
转换为Series
:stack
,从向量变为矩阵Series
转换为DataFrame
:unstack
,将矩阵拉直成向量
这里两方面转换都使用的是字典序的排序。如果报错,则用 xxx.index_sort
指令,将其排序,再进行操作。
df = trans.unstack()
print("DataFrame =\n", df)
print("*"*30)
srs = df.stack()
print("Series =\n", srs)
>>> DataFrame =
de en
five Funf Five
four Vier Four
one Eins One
three Drei Three
two Zwei Two
******************************
Series =
five de Funf
en Five
four de Vier
en Four
one de Eins
en One
three de Drei
en Three
two de Zwei
en Two
dtype: object
建 DataFrame 的时候可以直接使用两组 index
,但是要注意:两个的长度必须是等长的:(这里注意,columns
必须要是一个列表)
df = pd.DataFrame(digits, index = [["One", "One", "Two", "Two", "Three", "Three",
"Four", "Four", "Five", "Five"],
["En", "De", "En", "De", "En",
"De", "En", "De", "En", "De"]], columns = ["trans"])
print(df)
>>> trans
One En One
De Eins
Two En Two
De Zwei
Three En Three
De Drei
Four En Four
De Vier
Five En Five
De Funf
Cpt 4. DataFrame 的合并
运用 concat
函数,如果有重复的索引可以依靠内部的(verify_integreity
如果不完整则报错; ignore_index
两种参数进行处理,设置为 True
则就忽略重复;或是用 key
设置多级索引,传入一个列表,列表元素个数与合并的数量一致),一般尽量避免出现这种情况(比如有相同 index 的数据的合并在 R 语言中有 left_join
这种函数)。
def make_def(cols, ind):
data = {c:[str(c) + str(i) for i in ind] for c in cols}
return pd.DataFrame(data, ind)
df1 = make_def("ABC", range(3))
df2 = make_def("DEF", range(4, 7))
df = pd.concat([df1, df2], sort = True)
print(df)
>>> A B C D E F
0 A0 B0 C0 NaN NaN NaN
1 A1 B1 C1 NaN NaN NaN
2 A2 B2 C2 NaN NaN NaN
4 NaN NaN NaN D4 E4 F4
5 NaN NaN NaN D5 E5 F5
6 NaN NaN NaN D6 E6 F6
join函数:
-
直接
concat
就是叠加,空的用 NAN 补充; -
设置为
inner
就是取交集; -
设置为axes就是只取某一个 DataFrame 的列名作为所有的索引。
df1 = make_def("ABC", [1,2])
df2 = make_def("BCD", [3,4])
print(pd.concat([df1, df2]))
print("*"*30)
# 交集
print(pd.concat([df1, df2], join = 'inner'))
print("*"*30)
# 保留列
print(pd.concat([df1, df2], join_axes = [df1.columns]))
>>> A B C D
1 A1 B1 C1 NaN
2 A2 B2 C2 NaN
3 NaN B3 C3 D3
4 NaN B4 C4 D4
******************************
B C
1 B1 C1
2 B2 C2
3 B3 C3
4 B4 C4
******************************
A B C
1 A1 B1 C1
2 A2 B2 C2
3 NaN B3 C3
4 NaN B4 C4
******************************
Remark:
这里引入 merge
函数,与 R 语言 tydeverse
包中的 left _join
实现效果相似,会自动根据前面的索引进行合并,但是默认会删除所有的包含 NaN
的列,这点是与 left_join
不同的。
df1 = make_def("ABC", [1,2,1,2])
df2 = make_def("BCD", [1,2])
df3 = pd.merge(df1, df2)
print(df3)
>>> A B C D
0 A1 B1 C1 D1
1 A1 B1 C1 D1
2 A2 B2 C2 D2
3 A2 B2 C2 D2
嵌套在 merge
中还有一个比较强大的操作,是与 left_join
完全相同的操作:left_on
,right_on
,用的时候要指明两条 index
下值是一样的,比如一个里的 names
一个里面的 my_name
。用法如下:
pd.merge(df1, df2, left_on = "names", right_on = "my_names")
如果两边参数一样,直接用 on
,然后后面接索引。如果要改名字,则需要在 merge
中添加参数进行修改,可以指定列的 index
。
df3 = pd.merge(df1, df2, on = "name", suffixes = ["01", "02"])
Cpt 5. pandas数据清洗实战操作
xxx.describe()
或是 xxx.groupby
与 R 语言中的 summary
和 tydeverse
包中的groupby
的用法不同,但是作用相同。
使用方法:
groupby[第一个方法][第二个方法].操作()
操作是指求中位数或是求平均值等操作。
rng = np.random.RandomState(0)
rng = np.random.RandomState(0)
df = pd.DataFrame({"key":list("ABCABC"),
"data1":range(100,106),
"data2":rng.randint(0,10,6)},
columns = ["key", "data1", "data2"])
print(df)
print("*"*40)
print(df.describe())
>>> key data1 data2
0 A 100 5
1 B 101 0
2 C 102 3
3 A 103 3
4 B 104 7
5 C 105 9
****************************************
data1 data2
count 6.000000 6.000000
mean 102.500000 4.500000
std 1.870829 3.209361
min 100.000000 0.000000
25% 101.250000 3.000000
50% 102.500000 4.000000
75% 103.750000 6.500000
max 105.000000 9.000000
与 R 语言的 summary
一样,取了各分位点的值,以及均值方差等信息。
Res = df.groupby("key").aggregate(["min", np.median, np.max])
print(Res)
>>> data1 data2
min median amax min median amax
key
A 100 101.5 103 3 4.0 5
B 101 102.5 104 0 3.5 7
C 102 103.5 105 3 6.0 9
groupby
就是按类别,然后 aggregate
进行累加,这里的操作就是将所有 key 的值,及逆行统计量的描述。这些都与 R 语言的操作效果是一样的。
filter()
函数,里面可以写自定义的函数、或是比较符号。返回满足条件的DataFrame。
apply()
函数,对这一行或是这一列统一进行操作,括号内写入一个函数。
def norm_data(x):
x["data1"] = x["data1"] / x["data1"].sum()
return x
rst = df.groupby("key").apply(norm_data)
print(rst)
>>> key data1 data2
0 A 0.492611 5
1 B 0.492683 0
2 C 0.492754 3
3 A 0.507389 3
4 B 0.507317 7
5 C 0.507246 9