В df есть столбец ABC_81, ABC_y, ABC_aa, ZXC_aa, ZXC_5, ZXC_hi
:
data = {
'ABC_81': [1, 2, 3],
'ABC_y': [4, 5, 6],
'ABC_aa': [7, 8, 9],
'ZXC_aa': [10, 11, 12],
'ZXC_5': [13, 14, 15],
'ZXC_hi': [16, 17, 18],
'PPP_tr' : [88,55,99],
'QWE_gf' : [78,98,14]
}
Двигаясь слева направо в df, я хочу сохранить первый экземпляр имени столбца, начинающийся с ABC и ZXC, и удалить другие столбцы, начинающиеся с ABC и ZXC.
Keep ABC_81,
Drop ABC_y, ABC_aa
Сходным образом
Keep ZXC_aa,
Drop ZXC_5, ZXC_hi
и так далее
Результат должен быть:
data = {
'ABC_81': [1, 2, 3],
'ZXC_aa': [10, 11, 12],
'PPP_tr' : [88,55,99],
'QWE_gf' : [78,98,14]
}
Кроме того, можно ли это сделать, не зная имен столбцов?
Да, вы можете добиться этого, не зная явно имена столбцов, используя pandas. Например, ты можешь сделать это, братан:
import pandas as pd
data = {
'ABC_81': [1, 2, 3],
'ABC_y': [4, 5, 6],
'ABC_aa': [7, 8, 9],
'ZXC_aa': [10, 11, 12],
'ZXC_5': [13, 14, 15],
'ZXC_hi': [16, 17, 18]
}
df = pd.DataFrame(data)
# Create a list to store the columns to keep
columns_to_keep = []
# Iterate over the columns of the DataFrame
for col in df.columns:
# Check if the column starts with 'ABC' or 'ZXC'
if col.startswith('ABC') or col.startswith('ZXC'):
# Append the first occurrence of the column name to the list
if col[:3] not in columns_to_keep:
columns_to_keep.append(col[:3])
# Filter the DataFrame to keep only the columns in columns_to_keep
df_filtered = df[[col for col in df.columns if col[:3] in columns_to_keep]]
print(df_filtered)
Этот код перебирает столбцы DataFrame и проверяет, начинается ли каждый столбец с «ABC» или «ZXC». Затем он добавляет первые три символа имени столбца в список columns_to_keep, если это первое вхождение. Наконец, он фильтрует DataFrame, чтобы сохранить только столбцы, присутствующие в columns_to_keep. (надеюсь, я хорошо понимаю)
Предполагая, что фиксированная часть стоит перед подчеркиванием, вы можете использовать регулярное выражение, чтобы извлечь префикс, затем идентифицировать первое значение с помощью дублированного и, наконец, использовать логическое индексирование, чтобы выбрать первый столбец для каждого префикса:
m = ~df.columns.str.extract(r'^([^_]+)', expand=False).duplicated()
out = df.loc[:, m]
В качестве однострочника:
out = df.loc[:, ~df.columns.str.extract(r'^([^_]+)', expand=False).duplicated()]
Выход:
ABC_81 ZXC_aa PPP_tr QWE_gf
0 1 10 88 78
1 2 11 55 98
2 3 12 99 14
Промежуточные продукты:
df.columns.str.extract(r'^([^_]+)', expand=False)
# Index(['ABC', 'ABC', 'ABC', 'ZXC', 'ZXC', 'ZXC'], dtype='object')
df.columns.str.extract(r'^([^_]+)', expand=False).duplicated()
# array([False, True, True, False, True, True, False, False])
~df.columns.str.extract(r'^([^_]+)', expand=False).duplicated()
# array([ True, False, False, True, False, False, True, True])
При необходимости вы можете добавить дополнительные условия:
# extract prefix
prefix = df.columns.str.extract(r'^([^_]+)', expand=False)
# identify duplicated columns that match ABC/ZXC
m = prefix.isin(['ABC', 'ZXC']) & prefix.duplicated()
# select all but duplicated ABC/ZXC
out = df.loc[:, ~m]
Ваше решение работает. Идя дальше, допустим, у нас также есть PPP_tr и PPP_aa, которые нельзя удалять? следует отбросить только ABC и ZXC.
Вы можете добавить второе условие. Посмотреть обновление
Для моих исходных данных (как вы отвечаете) ваш код не работает. Я обновил данные, включив в них некоторые столбцы, которые не следует удалять: «PPP_tr» и «QWE_gf».