分享

pandas 小技巧

 天上飞鸡 2020-12-29

1、pandas.DataFrame.set_index()

DataFrame.set_index(keys,drop=True,append=False,inplace=False,verify_integrity=False)
将DataFrame中的列转化为行索引

举例说明

>df = pd.DataFrame.from_dict({"a":[1,1], "b":[2,2], "c":[3,3]})
>print(df) 
输出
   a  b  c
0  1  2  3
1  1  2  3

将其中任意一列变成行索引,例如“a”

>df1 = df.set_index("a")
>print(df1)
输出
   b  c
a      
1  2  3
1  2  3

也可以将多列变成行索引

>df2 = df.set_index(["a","b"])
>print(df2)
输出
     c
a b   
1 2  3
  2  3

2、DataFrame.reset_index()

DataFrame.reset_index(level=None, drop=False,inplace=False, col_level=0, col_fill="")
1、重置DataFrame的索引,并使用默认索引。
2、如果DataFrame有多个行索引,则此方法可以删除一个或多个行索引级别,可以让行索引变成列。
3、参数说明
level:只从行索引中删除给定的索引级别,默认情况下删除所有级别。level是原始df的index的层级,可用数字/名称表示。用数字表示的时候,0代表第一级行索引,1代表第二级行索引,以此类推。
drop:True/False 表示释放出来的行索引,变成列之后,是否要删除。
col_level:将释放出来的行索引作为列,插入到指定的列级别位置,默认情况下,它被插入到第一层。col_level表示列的层级。
col_fill:将释放出来的行索引作为列,插入到指定的列级别位置,并且给该列设置列名,如果没有设置,则重复其行索引名。

举例说明

>df2
输出
     c
a b   
1 2  3
  2  3

可以看出,df2的行索引有2级,分别是“a”和“b”。用名称表示层级的话,就是level=‘a’、level=‘b’。用数字表示层级的话,就是level=0和level=1

# 我们可以用下面的语句查看一个df的行索引的层级个数
>print(df2.index.levels)
输出
[[1], [2]]
就是有2个的意思

将行索引“b”变成列,并且保留该列:行索引“b”的层级是level=1

>df2_1 = df2.reset_index(level=1) #level="b"和level=1是一样的
>print(df2_1)
输出
   b  c
a      
1  2  3
1  2  3
>df2_2 = df2.reset_index(level=1, drop=True)  #不保留该列
>print(df2_2)
输出
   c
a   
1  3
1  3

最常使用的地方
df.reset_index()一般与 df.groupby().apply(lambda x: 函数(x))在一起搭配使用:我们在进行数据处理的时候,经常会对数据进行分组操作,然后对每一个分组内的数据再进行这样或者那样的聚合计算,就会使用到 df.groupby().apply(lambda x: 函数(x))的组合:使用groupby对df进行分组,生成若干个df_sub,然后对每一个分组df_sub又使用apply(lambda x: 函数(x))进行操作,如果lambda函数所表示的操作是生成一个新的df,那么groupby之后的df就拥有了两个行索引,一个是自己原先就有的,一个是apply()生成的。

但是apply(函数)生成的行索引,没有什么实际的用途,此时需要去掉,这时候就用到了reset_index(),具体使用方法如下:

# 有一个原始df,对它进行分组操作,根据列score进行分组,然后对每一组再进行统计计算
df_result_tmp = df.groupby("score").apply(lambda x: trans(x, list_1))
df_result = df_result_tmp.reset_index(level=1, drop=True)
# df_result就是我们所要的结果。

其中,函数trans是自己根据实际业务需求定义的一个函数,如下

def trans(df_sub, list_1):
# 输入:df_sub是原始df经过groupby之后的一个分组;list_1就是一个参数
# 返回:一个新的df_sub_new
    return pd.DataFrame.from_dict(
{"A": df_sub[df_sub["label"] == "A"].shape[0] * 1.0 / df_sub.shape[0],
"B": df_sub[df_sub["label"] == "B"].shape[0] * 1.0 / df_sub.shape[0]
}, orient='index').T
    # 如果一个字典中,每一个key的值只有一个,那么在使用pd.DataFrame.from_dict(marix_dict, orient='columns')时就会报错,解决方式就是orient='index',然后再进行转置。

上面的例子中,apply(lambda x: trans(x, list_1))中的trans函数,对每一个分组之后的df_sub进行操作,生成了一个新的df_sub_new,此时df_sub_new是有一个默认的index的。这就导致df_result_tmp有两级行索引,如下:

>print(df_result_tmp)

                        A            B  
score                                                                        
[0, 439)       0      0.0000      0.0000
[439, 459)     0      0.0000      0.0000
[459, 479)     0      0.0443      0.0000
[479, 499)     0      0.7884      0.0000
[499, 520)     0      0.1547      0.0275
[520, 999)     0      0.0093      0.7970

一个行索引是score,索引级别level=0;另一个行索引是全是0的那一列,索引级别level=1。实际上我们在使用的时候,level=1的行索引是不需要的,所以有必要给去掉,保留的话可能对后续操作有不可知的影响。此时就需要用到reset_index()函数了:

>df_result = df_result_tmp.reset_index(level=1, drop=True)
>print(df_result)

                 A            B  
score                                                                        
[0, 439)       0.0000      0.0000
[439, 459)     0.0000      0.0000
[459, 479)     0.0443      0.0000
[479, 499)     0.7884      0.0000
[499, 520)     0.1547      0.0275
[520, 999)     0.0093      0.7970

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多