workbench tabular data怎么增加一行_pandas 索引名重名 怎么办

pandas 索引名重名 怎么办

本文中索引名包括行名和列名,也就是indexcolumn

也许很少有人注意到,pandas中索引名是可以重名的。

试一下。

import pandas as pdimport numpy as npdata = pd.DataFrame(np.random.randint(1,10,(5,5)),columns=list('aaabb'),index = list('11122'))

out:

    a    a    a    b    bc    1    8    6    6    2c    8    9    4    9    7c    7    6    7    6    5d    2    7    8    1    6d    2    3    1    5    5

由此出现的问题,是我们在取值时取出的是dataframe而不是series

data['a']

out:

    a    a    ac    1    8    6c    8    9    4c    7    6    7d    2    7    8d    2    3    1
data.loc['c',:]

out:

    a    a    a    b    bc    1    8    6    6    2c    8    9    4    9    7c    7    6    7    6    5
data.loc[:,'a']

out:

    a    a    ac    1    8    6c    8    9    4c    7    6    7d    2    7    8d    2    3    1

这可能就直接导致了后面的bug出现。

很少有人希望索引名重名,但是问题总是不经意间来临。

data1 = pd.DataFrame(np.random.randint(1,10,(2,3)),columns=list('abc'),index = list('cd'))data2 = pd.DataFrame(np.random.randint(1,10,(2,3)),columns=list('bcd'),index = list('cd'))
pd.concat([data1,data2],axis=0)

out:

    a    b    c    dc    1.0    9    8    NaNd    5.0    6    6    NaNc    NaN    8    3    7.0d    NaN    9    3    5.0

行名重复。

pd.concat([data1,data2],axis=1)

out:

    a    b    c    b    c    dc    1    9    8    8    3    7d    5    6    6    9    3    5

列名重复。

有效的避免途径是concat时使用ignore_index参数。

pd.concat([data1,data2],axis=0,ignore_index=True)

out:

    a    b    c    d0    1.0    9    8    NaN1    5.0    6    6    NaN2    NaN    8    3    7.03    NaN    9    3    5.0

或者将verify_integrity参数设为Trueconcat便会在出现重名时报错。

如果感觉到可能有重名,可以用has_duplicates检验一下。

data.columns.has_duplicates

out:

True

去除重名

当遇到重名时,就需要有效的去除重名。

下面均以列名为例。

最简单的方法是删除重名。(废话)

data = pd.DataFrame(np.random.randint(1,10,(3,10)), columns=list('aabbccdefg'))data.loc[:,~data.columns.duplicated()]

out:

    a    b    c    d    e    f    g0    5    3    8    5    8    9    11    5    1    9    4    1    6    32    2    4    3    2    2    2    8

这里必须使用lociloc,直接[]会出现value_error。因为在[]中使用布尔列表取值会被认为是按行取值。

但是常见情况是必须保留并且将索引名唯一化。

重名 重命名

首先想到的方法是使用rename

data.rename(columns={'a':'a_1'},inplace=True)data

out:

    a_1    a_1    b    b    c    c    d    e    f    g0    5    8    3    9    8    1    5    8    9    11    5    4    1    8    9    6    4    1    6    32    2    4    4    4    3    1    2    2    2    8

但是rename将所有a都改为了a_1

rename失败后,唯一的办法就是自己重新构造columns并赋值了。

简单的做法是在所有重名的索引名后面加一个东西。

data.columns = list('aabbccdefg')data.columns = [j + '_1' if data.columns.duplicated()[i] else j for i,j in enumerate(data.columns)]

out:

    a    a_1    b    b_1    c    c_1    d    e    f    g0    5    8    3    9    8    1    5    8    9    11    5    4    1    8    9    6    4    1    6    32    2    4    4    4    3    1    2    2    2    8

但是这个只能对付重复次数小于等于2的情况。

可以用下面的代码做一个先行核查。

data.columns = list('aabbccdefg')np.all(data.columns.value_counts() <= 2)

out:

True

在遇到多重复(>2)时,可以用一下循环,不断的往重名列后面加东西。

data.columns=list('aabbbccccc')while data.columns.has_duplicates:    data.columns = [j + '_' if data.columns.duplicated()[i] else j for i,j in enumerate(data.columns)]data

out:

    a    a_    b    b_    b__    c    c_    c__    c___    c____0    5    8    3    9    8    1    5    8    9    11    5    4    1    8    9    6    4    1    6    32    2    4    4    4    3    1    2    2    2    8

也可以稍改一下前面的代码,变为后面添加列的整数位置。

data.columns=list('aabbbccccc')data.columns = [j + f'_{i}' if data.columns.duplicated()[i] else j for i,j in enumerate(data.columns)]data

out:

    a    a_1    b    b_3    b_4    c    c_6    c_7    c_8    c_90    5    8    3    9    8    1    5    8    9    11    5    4    1    8    9    6    4    1    6    32    2    4    4    4    3    1    2    2    2    8

但是总归不是很完美,我们始终不能知道,这一列是该列名第几个重复。

如果需要将第几个这种参数,也加上去,就不能单纯的使用一行列表生成式解决了。

改变一下思路,只有逐个处理的时候我们才能顺利的知道重复总个数,进而判断这是第几个重复。

data.columns=list('aabbbccccc')for index in data.columns.value_counts()[data.columns.value_counts()>=2].index:    duplicate = (data.columns==index) & (data.columns.duplicated())    data.columns = [j + f'_{np.sum(duplicate[:i+1])}' if duplicate[i] else j for i,j in enumerate(data.columns)]data

out:

    a    a_1    b    b_1    b_2    c    c_1    c_2    c_3    c_40    5    8    3    9    8    1    5    8    9    11    5    4    1    8    9    6    4    1    6    32    2    4    4    4    3    1    2    2    2    8

Perfect!

这里,首先通过value_counts获得需要处理的列名。然后最重要的是通过生成duplicate(结合列名和是否重复)确定需要的处理的是哪几列,然后一个sum就能很轻松的确定这是第几个了。

这样的处理在需要更改时也很简单,比如希望所有重复的列名从第一个开始就加上后缀。

data.columns=list('aabbbccccc')for index in data.columns.value_counts()[data.columns.value_counts()>=2].index:    duplicate = data.columns==index    data.columns = [j + f'_{np.sum(duplicate[:i+1])}' if duplicate[i] else j for i,j in enumerate(data.columns)]data

out:

    a_1    a_2    b_1    b_2    b_3    c_1    c_2    c_3    c_4    c_50    5    8    3    9    8    1    5    8    9    11    5    4    1    8    9    6    4    1    6    32    2    4    4    4    3    1    2    2    2    8

或者希望将后缀从0开始。

data.columns=list('aabbbccccc')for index in data.columns.value_counts()[data.columns.value_counts()>=2].index:    duplicate = data.columns==index    data.columns = [j + f'_{np.sum(duplicate[:i])}' if duplicate[i] else j for i,j in enumerate(data.columns)]pythondata

out:

    a_0    a_1    b_0    b_1    b_2    c_0    c_1    c_2    c_3    c_40    5    8    3    9    8    1    5    8    9    11    5    4    1    8    9    6    4    1    6    32    2    4    4    4    3    1    2    2    2    8

甚至列名无脑按个数重复。

data.columns=list('aabbbccccc')for index in data.columns.value_counts()[data.columns.value_counts()>=2].index:    duplicate = data.columns==index    data.columns = [j + f'{index}' * np.sum(duplicate[:i]) if duplicate[i] else j for i,j in enumerate(data.columns)]data

out:

    a    aa    b    bb    bbb    c    cc    ccc    cccc    ccccc0    5    8    3    9    8    1    5    8    9    11    5    4    1    8    9    6    4    1    6    32    2    4    4    4    3    1    2    2    2    8

都可以轻松满足需求。

行名处理也是一样的,你,学会了吗?

我是 SSSimon Yang,关注我,用code解读世界

b890645a71fe8d8f67b48d6e09007eba.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值