pandas 小技巧
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 c0 1 2 31 1 2 3
将其中任意一列变成行索引,例如“a”
>df1 = df.set_index("a")>print(df1)输出 b ca 1 2 31 2 3
也可以将多列变成行索引
>df2 = df.set_index(["a","b"])>print(df2)输出 ca 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输出 ca 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 ca 1 2 31 2 3>df2_2 = df2.reset_index(level=1, drop=True) #不保留该列>print(df2_2)输出 ca 1 31 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