首页 > 编程知识 正文

qpython,python中pandas库

时间:2023-05-04 00:33:18 阅读:39661 作者:3578

楔子

笔者曾经遇到过两种形式的数据。 那时,我确实不好住了。 最后解决了,方法不优雅,而且效率也不高。 如果想提高效率,就必须使用pandas提供的方法。 pandas一定可以作为一个强大的库优雅地解决。 当时用自己的方法解决后,就没有了。 但是最近又遇到了当时的情况,所以决定优雅地解决。 最后努力,总算找到了解决办法。 首先,让我们来看看当时难以居住的笔者的两种格式的数据和需求。

需求1 :

这些格式的数据包括:

科目名成绩

kwdhc国语90

kwdhc数学90

kwdhc英语90

dddlf国语91

dddlf数学91

dddlf英语91

xndfj国语92

xndfj数学92

xndfj英语92

我们会变成下面这样

姓名、国语、数学、英语

kwdhc 90 90 90

dddlf 91 91 91

xndfj 92 92 92

需求2 :

年龄兴趣

kwdhc 18舞蹈、歌曲、钢琴

dddlf 20歌曲、跳跃、说唱、篮球

xndfj 19古筝,翻译

我们会变成下面这样

年龄兴趣

kwdhc 18舞蹈

kwdhc 18歌曲

kwdhc 18钢琴

dddlf 20演唱

dddlf 20跳跃

dddlf 20 rap

dddlf 20篮球

xndfj 19古筝

xndfj 19翻译

解决需求1

未堆叠

是打印(df )

''''

科目分数

0 kwdhc国语90

1 kwdhc数学90

2 kwdhc英语90

3 dddlf国语91

4 dddlf数学91

5 dddlf英语91

6 xndfj国语92

7 xndfj数学92

8 xndfj英语92

''''

#为名称和科目设置索引,只提取“分数”,得到对应的二次索引Series对象

df=df.set_index([ '名称','科目' ] ) )

two_level_index_series=df[ '分数' ]

#这里得到的是具有辅助索引的series

打印(two _ level _ index _ series ) )

''''

科目名称

kwdhc国语90

数学90

英语90

dddlf国语91

数学91

英语91

xndfj国语92

数学92

英语92

Name:分数,dtype: int64

''''

#调用辅助索引的unstack方法可以得到DataFrame

#然后,主索引自动成为数据帧的索引,而辅助索引成为数据帧的列

new _ df=two _ level _ index _ series.un stack (

打印(new _ df )是

''''

科目数学英语语文

姓名

kwdhc 90 90 90

dddlf 91 91 91

xndfj 92 92 92

''''

#你怎么回来的? 但是有一个不完整的地方

#那就是这个new_df的索引和columns有名字

# index的名称为“名称”,columns的名称为“科目”。 因为原始series的两个索引被称为“名称”和“分数”

# rename_axis表示要重命名坐标轴

#这里首先清空columns的名称,继续查看索引不为空的原因

new _ df=new _ df.rename _ axis (columns=none )

打印(new _ df )是

''''

数学英语

姓名

kwdhc 90 90 90

dddlf 91 91 91

xndfj 92 92 92

''''

new_df=new_df.reset_index (

打印(new _ df )是

''''

姓名、数学、英文

0 kwdhc 90 90 90

1滴滴涕

lf 91 91 91

2 xndfj 92 92 92

"""

# 大功告成,如果index变为空的话,那么在reset_index之后,列名会变成index

# 但是如果原来索引有名字,reset_index,列名就是原来的索引名

pivot

pivot相当于是我们上面方法的一个化简,我们是把姓名作为索引、科目作为列、分数作为值

print(df)

"""

姓名 科目 分数

0 kwdhc 语文 90

1 kwdhc 数学 90

2 kwdhc 英语 90

3 dddlf 语文 91

4 dddlf 数学 91

5 dddlf 英语 91

6 xndfj 语文 92

7 xndfj 数学 92

8 xndfj 英语 92

"""

df = pd.pivot(df, index="姓名", columns="科目", values="分数")

print(df)

"""

科目 数学 英语 语文

姓名

kwdhc 90 90 90

dddlf 91 91 91

xndfj 92 92 92

"""

# 可以看到上面这一步,就直接相当于df.set_index(["姓名", "科目"])["分数"].unstack()

df = df.rename_axis(columns=None).reset_index()

print(df)

"""

姓名 数学 英语 语文

0 kwdhc 90 90 90

1 dddlf 91 91 91

2 xndfj 92 92 92

"""

解决需求二:

print(df)

"""

姓名 年龄 爱好

kwdhc 18 跳舞,唱歌,钢琴

dddlf 20 唱,跳,rap,篮球

xndfj 19 古筝,翻译

"""

df = df.set_index(["姓名", "年龄"])["爱好"].str.split(",", expand=True).stack().reset_index(drop=True, level=-1).reset_index().rename(columns={0: "爱好"})

print(df)

"""

姓名 年龄 爱好

0 kwdhc 18 跳舞

1 kwdhc 18 唱歌

2 kwdhc 18 钢琴

3 dddlf 20 唱

4 dddlf 20 跳

5 dddlf 20 rap

6 dddlf 20 篮球

7 xndfj 19 古筝

8 xndfj 19 翻译

"""

估计有人会懵逼,别急我们来一步一步拆解,不过在此之前我们先来介绍一下unstack和stack

unstack和stack

首先Series只有unstack,DataFrame既有unstack又有stack。对于Series来说,我们刚才说了,unstack是把该Series变成一个DataFrame,并且会把当前的一级索引变成DataFrame的对应索引、二级索引变成DataFrame的对应列,但如果不止二级呢?假设这个Series有8级索引呢?其实不管有多少级,假设n级,unstack不加参数的话,那么默认是把最后一级索引变成DataFrame的列,前面的n-1个索引则依旧会变成DataFrame的索引,当然也是n-1个。

为了和DataFrame做对比,我们就假设为2级索引。对于Series来说,unstack是把1级索引变成对应DataFrame的索引,2级索引是变成对应DataFrame的列。如果对DataFrame调用unstack,那么会把这个DataFrame转成一个具有二级索引的Series(如果这个DataFrame的索引只有一级的话),对应的索引变成具有二级索引的Series的二级索引,对应的列变成具有二级索引Series的一级索引。如果是stack的话,那么和Series正好是相反的,DataFrame的索引变成具有二级索引Series的一级索引,列变成具有二级索引Series的二级索引。

文字不好懂的话,看一张图

下面我们就来分析一下上面的那一长串

print(df)

"""

姓名 年龄 爱好

kwdhc 18 跳舞,唱歌,钢琴

dddlf 20 唱,跳,rap,篮球

xndfj 19 古筝,翻译

"""

# 我们是对"爱好"这个字段进行分解

# 那么将除了"爱好"之外的其它字段设置为索引

df = df.set_index(["姓名", "年龄"])

print(df)

"""

爱好

姓名 年龄

kwdhc 18 跳舞,唱歌,钢琴

dddlf 20 唱,跳,rap,篮球

xndfj 19 古筝,翻译

"""

# 筛选出"爱好"这个字段,此时得到的是一个具有二级索引的Series

# 索引的名字叫 "姓名"和"年龄"

s = df["爱好"]

print(s)

"""

姓名 年龄

kwdhc 18 跳舞,唱歌,钢琴

dddlf 20 唱,跳,rap,篮球

xndfj 19 古筝,翻译

Name: 爱好, dtype: object

"""

# 那么下面就对期望的字段进行分解

# 我们这个例子都是以逗号为分隔符,至于具体是什么则以实际数据为准

# 显然这里得到一个具有二级索引的DataFrame

df = s.str.split(",", expand=True)

print(df)

"""

0 1 2 3

姓名 年龄

kwdhc 18 跳舞 唱歌 钢琴 None

dddlf 20 唱 跳 rap 篮球

xndfj 19 古筝 翻译 None None

"""

# 调用stack,按照前面说的,会变成一个Series,索引就是DataFrame的索引再加上这个列变成的索引,显然列变成的索引就是三级索引了

# 可以看成是把DataFrame的索引看成一个整体作为对应Series的一级索引了

s = df.stack()

# 此时的数据已经像那么回事了

print(s)

"""

姓名 年龄

kwdhc 18 0 跳舞

1 唱歌

2 钢琴

dddlf 20 0 唱

1 跳

2 rap

3 篮球

xndfj 19 0 古筝

1 翻译

dtype: object

"""

# 然后调用reset_index,但是我们发现索引有三级,那么这样做就会导致,0 1 2 0 1 2..这些也变成了一列,当然可以之后drop掉

# 但是我们也可以直接删掉

# 于是我们可以加上一个drop=True,但是这样又把所有的index都删掉了,于是我们可以指定一个level

# 由于三级索引,那么最后一级就是2,当然可以直接指定为-1,表示最后一级,表示把最后一级索引删掉

s = s.reset_index(drop=True, level=-1)

print(s)

"""

姓名 年龄

kwdhc 18 跳舞

18 唱歌

18 钢琴

dddlf 20 唱

20 跳

20 rap

20 篮球

xndfj 19 古筝

19 翻译

dtype: object

"""

# 但是我们发现,上面的reset_index(drop=True, level=-1)并没有把前面的索引变成列

# 这是因为我们指定了level,如果不指定level,那么drop=True会把所有的索引都删掉

# 但指定了level只会删除对应级别的索引,而不会同时对前面的索引进行reset,于是需要再调用一次reset_index,此时就什么也不需要指定了

df = s.reset_index()

# 会自动进行笛卡尔乘积

print(df)

"""

姓名 年龄 0

0 kwdhc 18 跳舞

1 kwdhc 18 唱歌

2 kwdhc 18 钢琴

3 dddlf 20 唱

4 dddlf 20 跳

5 dddlf 20 rap

6 dddlf 20 篮球

7 xndfj 19 古筝

8 xndfj 19 翻译

"""

# 但是我们发现列名,是自动生成的0,于是再进行rename

df = df.rename(columns={0: "爱好"})

print(df)

"""

姓名 年龄 爱好

0 kwdhc 18 跳舞

1 kwdhc 18 唱歌

2 kwdhc 18 钢琴

3 dddlf 20 唱

4 dddlf 20 跳

5 dddlf 20 rap

6 dddlf 20 篮球

7 xndfj 19 古筝

8 xndfj 19 翻译

"""

# 此时就大功告成啦

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。