#python #pandas #csv
#python #pandas #csv
Вопрос:
Я очень новичок в Python, и сейчас я работаю над задачей, требующей от меня сохранения строк, которые появляются менее k раз из CSV-файла.
В основном файл CSV состоит из 3 столбцов. Первый столбец — это та часть, которую я должен рассмотреть. Так, например, если ‘a’ появилось менее 5 раз в этом столбце, мне нужно выбрать эти записи и сохранить их в новом CSV-файле.
Мне удалось использовать panda df['column name'].value_counts()
, чтобы подсчитать, сколько раз появлялась каждая строка. Теперь я пытаюсь понять, как на самом деле выбрать эти менее частые строки и сохранить их. У меня есть некоторые мысли, например, использовать цикл for для перебора всех строк и использовать if, чтобы проверить, появляются ли определенные данные в первом столбце меньше K раз. Часть, которую я не смог понять, по-видимому, заключается в том, как связать количество частот с определенными данными в этом столбце.
Ниже приведен скриншот моего файла данных, пример моих данных csv
Любая помощь высоко ценится! спасибо, ребята!
Комментарии:
1. Вам действительно нужно использовать Pandas для этой конкретной работы или проекта или разрешено использовать какие-либо альтернативы???
2. Я могу использовать все, что мне нравится. Pandas была всего лишь одной библиотекой, с которой я начинал. перед этим мне нужно было хэшировать столбец, поэтому я начал с Pandas
Ответ №1:
Вы упомянули pandas, и вот подход pandas:
import pandas as pd
# create sample data frame
data = [
(1, 2, 3),
(1, 4, 5),
(1, 6, 7),
(9, 10, 11),
(9, 12, 13),
]
df = pd.DataFrame(data, columns=('x', 'y', 'z'))
# keep rows with value in column 'x' appears at most 'ceiling' times
ceiling = 2
low_freq = df['x'].value_counts().loc[lambda x: x <= ceiling].index
# use boolean mask to find rows such that 'x' is in our low_freq list
mask = df['x'].isin(low_freq)
# print results
print(df[mask])
x y z
3 9 10 11
4 9 12 13
# use df[mask].to_csv(...) to write to csv file
Обновить:
Вот способ «разобрать» приведенный выше код. Например, что такое low_freq
? Это позволяет вам видеть каждый шаг преобразования — так что вы можете изменить / расширить подход.
df['x']
df['x'].value_counts()
df['x'].value_counts().loc[lambda x: x <= ceiling]
df['x'].value_counts().loc[lambda x: x <= ceiling].index
ОБНОВЛЕНИЕ 2
Очевидно, логика фильтрации работает не так, как ожидалось. Давайте попробуем другой подход:
import pandas as pd
# create sample data frame
data = [(0, 1, 2, ), (1, 1, 4, ), (2, 1, 6, ),
(3, 9, 10,), (4, 9, 12,), (5, 7, 21,)]
df = (pd.DataFrame(data, columns=('pos_id', 'device_id', 'base_mac'))
.set_index('pos_id'))
Теперь используйте groupby()
для подсчета количества вхождений каждого из них device_id
. Это количество переходит в новый столбец.
df['dev_id_count'] = (df.groupby('device_id')['device_id']
.transform('count'))
print(df)
device_id base_mac dev_id_count
pos_id
0 1 2 3
1 1 4 3
2 1 6 3
3 9 10 2
4 9 12 2
5 7 21 1
Последним шагом является фильтрация на основе этого нового столбца:
mask = df['dev_id_count'] <= 2
print(df[mask])
# output not shown, to save space
Комментарии:
1. эй, чувак, большое спасибо! Это действительно работает! если вы не возражаете, я разверну полную историю здесь. Короче говоря, я получил таблицу с 3 столбцами, первый из которых является жизненно важным. Он содержит буквенно-цифровые символы. Каждое значение представляет собой либо 4 цифры чисел, либо 4 буквенно-цифровых символа. остальные 2 столбца на самом деле не имеют значения. Что я пытаюсь здесь, так это проверить, соответствуют ли все строки / записи в выходных данных CSV K анонимности. Скажем, k = 5, я хотел бы выбрать те записи, которые появляются менее 5 раз, и сохранить их на данный момент для последующей обработки. Как вы думаете, я на правильном пути?
2. Да, я думаю, вы на правильном пути. Я добавил короткое обновление, показывающее, как получить промежуточные результаты в коде pandas. Таким образом, вы можете изменять / расширять для своего проекта. Также проверьте
.groupby()
для подсчета количества вхождений в столбец.3. Я действительно ценю вашу помощь здесь, чувак, однако, похоже, я столкнулся с некоторой проблемой. ваш пример прекрасно работает с этим методом, но когда я попробовал его в своем реальном техническом паспорте, он показался «неправильным»? Исходный лист данных csv содержит 2700 строк или записей, я говорю, что после использования этого метода я получаю на выходе таблицу данных с 2500 строками. мне кажется, это не подходит, поскольку я уже хэшировал таблицу. было бы странно, если бы этот метод мог привести к тому, что почти 80% строк «появятся менее k раз». Не могли бы вы дать мне еще немного подсказок? Я пытаюсь загрузить несколько скриншотов в вопросе
4. извините, я не имел в виду, что продемонстрированный вами метод вызвал проблему. Я имею в виду, что вывод csv меня удивил. перед шагом, о котором мы говорим, я просто хэшировал всю таблицу csv. как вы думаете, это проблема самих данных или я сделал что-то не так?
5. эй, чувак, мне просто интересно, каков именно результат твоего кода? содержит ли результирующий CSV-файл все строки, которые отображаются менее K раз, или эти строки отображаются более K раз?
Ответ №2:
Вот стандартная версия библиотеки:
import csv
THRESHOLD = 5
def get_data(filename, column, threshold=THRESHOLD):
"""Return list of dict of rows where count of the column is smaller than the threshold and the headers of the CSV file"""
with open(filename, 'r') as f:
csv_reader = csv.DictReader(f)
# get all rows where there's NO data in the column
data = [line for line in csv_reader if not line.get(column)]
if len(data) < threshold:
return data, csv_reader.fieldnames
def write_data(filename, data, headers):
"""Write data to a CSV"""
with open(filename, 'w') as f:
csv_writer = csv.DictWriter(f, fieldnames=headers)
csv_writer.writeheader()
csv_writer.writerows(data)
data, headers = get_data(filename='file.csv', column='a')
write_data(filename='filter.csv', data=data, headers=headers)