Удалить общую подстроку с помощью метода groupby

Я хотел бы удалить дубликаты с общей подстрокой, общая подстрока — это самая короткая строка в фрейме данных.

Я пробую приведенный ниже код, и он работает так, как ожидалось, но я хотел бы улучшить код. после группировки логика фильтра добавляется функцией 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

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам нужно найти имена пакетов, которые являются корневыми именами, что вы можете сделать, проверив, является ли какой-либо другой пакет префиксом текущего имени пакета:

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 03.04.2024 17:00

@beetlej извини за медленный ответ, занятой день. Я добавил редактирование, которое будет выполнять проверку корня для каждой группы.

Nick 04.04.2024 07:19

Другие вопросы по теме