Я хотел бы удалить дубликаты с общей подстрокой, общая подстрока — это самая короткая строка в фрейме данных.
Я пробую приведенный ниже код, и он работает так, как ожидалось, но я хотел бы улучшить код. после группировки логика фильтра добавляется функцией reformat.
import re
import pandas as pd
import tabulate
def dumpdf(df):
s = tabulate.tabulate(df, tablefmt='plain', headers='keys', showindex=True)
print(s)
return
def reformat(df):
dfg = df.groupby('name')
flag = False
for name,df in dfg:
item = []
df = df.sort_values(by = "package", key=lambda x: x.str.len())
data = []
for idx,row in df.iterrows():
pkg = row['package']
df.loc[df['package'].str.startswith(pkg, na=False), 'package'] = pkg
df = df[df.duplicated(['package'], keep='first') == False]
df = df.reset_index(drop=True)
if len(df) > 0:
if flag == False:
flag = True
out = df
else:
out = pd.concat([out,df],ignore_index=True)
return out
def main():
data = [
['A','com.example'],
['A','com.example.a'],
['A','com.example.b.c'],
['A','com.fun'],
['B','com.demo'],
['B','com.demo.b.c'],
['B','com.fun'],
['B','com.fun.e'],
['B','com.fun.f.g']
]
df = pd.DataFrame(data,columns=['name','package'])
df = reformat(df)
df = df.groupby('name', as_index=False).agg('\n'.join)
dumpdf(df)
return
main()
Выход:
name package
0 A com.fun
com.example
1 B com.fun
com.demo






Вам нужно найти имена пакетов, которые являются корневыми именами, что вы можете сделать, проверив, является ли какой-либо другой пакет префиксом текущего имени пакета:
def is_root_package(pkg, df):
return not any(pkg.startswith(p) and len(pkg) > len(p) for p in df['package'])
Теперь замаскируйте фрейм данных с помощью этой функции и сгруппируйте по name:
mask = df['package'].apply(is_root_package, df=df)
out = df[mask].groupby('name', as_index=False).agg('\n'.join)
Выход:
name package
0 A com.example\ncom.fun
1 B com.demo\ncom.fun
Если возможно, что группа может содержать все значения, имеющие префикс в другой группе, например. в com.fun есть df, но в конкретной группе есть только com.fun.* пакеты, вам нужно будет проверять пакеты отдельно для каждой группы. Вы можете сделать это с помощью этого кода:
# sample data
data = {
'name': ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B'],
'package': ['com.example', 'com.example.a', 'com.example.b.c', 'com.fun', 'com.demo', 'com.demo.b.c', 'com.fun.e', 'com.fun.e.f', 'com.fun.e.g']
}
df = pd.DataFrame(data)
def get_root_packages(g):
return '\n'.join(pkg for pkg in g if not any(pkg.startswith(p) and len(pkg) > len(p) for p in g))
out = df.groupby('name', as_index=False).agg(get_root_packages)
Выход:
name package
0 A com.example\ncom.fun
1 B com.demo\ncom.fun.e
@beetlej извини за медленный ответ, занятой день. Я добавил редактирование, которое будет выполнять проверку корня для каждой группы.
Хороший ответ, я думаю, что один из случаев — это область проверки корневого проекта. теперь это весь фрейм данных, как мы можем ограничить проверку корня для каждой группы? Возможно, у нас разные корневые уровни.