根据其他行的值删除行

时间:2021-01-20 16:59:38

标签: python pandas dataframe

我想按类型国家对数据框进行分组,并删除那些较长的电话号码Prefix,如果有较短的前缀相同的类型国家

例如基于以下输入:

<头>
前缀 类型 国家
43 修复线 奥地利
431 修复线 奥地利
43650 移动 奥地利
436501 移动 奥地利
43676 移动 奥地利

我想要以下输出。

<头>
前缀 类型 国家
43 修复线 奥地利
43650 移动 奥地利
43676 移动 奥地利

431 被删除,因为已经存在与 431431 相同类型和国家/地区的前缀 43 > 以 43 开头。

436501 被删除,因为已经存在与 436501436501 相同类型和国家/地区的前缀 43650 > 以 43650 开头。

我对 Pandas 没有太多经验。 我的第一次尝试是这个,但这需要太长时间:

for index, row in data.iterrows():
    for index2, row2 in data.iterrows():
        if index2 > index and row['Type'] == row2['Type'] and row['Country'] == row2['Country'] and row['Prefix'].startswith(row2['Prefix']):
            data.drop(index, inplace=True)
            break

2 个答案:

答案 0 :(得分:1)

我认为最明智的做法是先将 Prefix 切片为想要的并知道长度,然后删除重复项。

df = pd.DataFrame({'Prefix':[43, 431, 43650, 436501, 43676], 
                   'Type':['Fixline', 'Fixline', 'Mobile', 'Mobile', 'Mobile'], 
                   'Country':['Austria']*5})

df['Prefix'] = df[['Prefix', 'Type']].apply(lambda x: str(x[0])[:2] if x[1]=='Fixline' else str(x[0])[:5], axis=1)
df = df.drop_duplicates()
df
>>>
  Prefix     Type  Country
0     43  Fixline  Austria
2  43650   Mobile  Austria
4  43676   Mobile  Austria

答案 1 :(得分:1)

您的 DataFrame 中的 Prefix 列可能是 int 类型, 所以第一件事就是把它转换成String

df.Prefix = df.Prefix.astype(str)

然后定义2个函数:

  1. 检查当前行是否存在的函数 Prefix 较短的另一行,这也是“起始部分” “我的”前缀

    def hasShorter(row, grp):
        myPref = row.Prefix
        ind = row.name
        prefsToCompare = grp.drop(ind).Prefix
        # Leave only shorter Prefixes
        prefsToCompare = prefsToCompare[prefsToCompare.str.len() < len(myPref)]
        if prefsToCompare.size == 0:
            return False  # No rows with shorter prefix
        # Is any other Prefix less specific?
        return prefsToCompare.apply(lambda x: myPref.startswith(x)).any()
    
  2. 应用于每个组的函数 - 过滤器,消除行 没有任何更短的“邻居前缀”(以相同的开头 字符):

    def groupFilter(grp):
        return grp[~grp.apply(hasShorter, axis=1, grp=grp)]
    

然后,要获得预期的结果,请运行:

result = df.groupby(['Type', 'Country'], as_index=False,
    group_keys=False).apply(groupFilter)

对于您的数据样本,结果是:

  Prefix     Type  Country
0     43  Fixline  Austria
2  43650   Mobile  Austria
4  43676   Mobile  Austria

如果需要,将 Prefix 列转换回 int。 或者,该列最初是并且应该保持为 str 类型 (你的前缀只是代码,不小心只由数字组成, 但应该被视为字符串)?