Как объединить несколько CSV файлов в один: 4 способа с дедупликацией

Алексей Петров · · 9 мин чтения

У вас пять файлов с телефонными номерами из разных источников: выгрузка из CRM, экспорт из рекламного кабинета, база с прошлой рассылки, данные из партнёрской программы и список с конференции. Общий размер — 350 тысяч контактов. Задача: объединить всё в один файл, удалив дубликаты.

Объединение CSV-файлов — частая операция при работе с данными. В этой статье разберём четыре способа: от примитивного копирования до специализированных инструментов с автоматической дедупликацией. Каждый метод протестирован на реальных данных с замером времени и оценкой качества результата.

Когда нужно объединять CSV-файлы

Типичные сценарии из практики:

Главная проблема при объединении — дубликаты. Если просто склеить файлы, один и тот же номер может встретиться 3–5 раз. Результат: переплата за рассылку, повторные звонки клиентам, потеря репутации. Разберём, как этого избежать.

Ручное копирование

Самый простой, но наименее эффективный подход — открыть все файлы и скопировать содержимое в один.

Как это делается

  1. Создайте новый файл merged.csv
  2. Откройте первый файл в текстовом редакторе или Excel
  3. Скопируйте всё содержимое (Ctrl+A, Ctrl+C)
  4. Вставьте в merged.csv
  5. Повторите для остальных файлов
  6. Сохраните результат

Проблемы этого подхода

Проблема Последствия
Дубликаты остаются Переплата за рассылку, повторные обращения к клиентам
Заголовки CSV повторяются Строка с названиями колонок попадает в данные
Долго и скучно На 10 файлов уходит 15–20 минут
Высокий риск ошибки Можно пропустить файл или скопировать дважды

Пример: вы объединили пять файлов по 50 тысяч номеров. В итоговом файле оказалось 250 тысяч строк. Но реальных уникальных номеров может быть всего 180 тысяч — остальное дубли. Если вы загрузите эту базу в сервис рассылок, заплатите за 70 тысяч лишних контактов.

Вердикт: подходит только для 2–3 маленьких файлов, когда вы уверены, что дублей нет. Для остальных случаев — неэффективно и опасно.

Командная строка

В Unix-системах (Linux, macOS) объединение файлов делается одной командой. В Windows есть аналогичные инструменты.

Команда cat (Linux/macOS)

# Простое объединение без дедупликации
cat файл1.csv файл2.csv файл3.csv > merged.csv

# Или все CSV файлы в папке
cat *.csv > merged.csv

# Убрать заголовки из всех файлов кроме первого
cat файл1.csv > merged.csv
tail -n +2 файл2.csv >> merged.csv
tail -n +2 файл3.csv >> merged.csv

Параметры:

PowerShell и CMD (Windows)

# PowerShell: объединение файлов
Get-Content файл1.csv, файл2.csv, файл3.csv | Set-Content merged.csv

# Или все CSV в папке
Get-Content *.csv | Set-Content merged.csv

# CMD: более примитивный способ
copy файл1.csv + файл2.csv + файл3.csv merged.csv

Дедупликация через командную строку

После объединения можно удалить дубликаты с помощью sort и uniq:

# Unix: объединить и удалить дубли
cat файл1.csv файл2.csv файл3.csv | sort -u > merged_unique.csv

# Или в два этапа
cat *.csv > merged.csv
sort -u merged.csv > merged_unique.csv

Важно: sort -u сортирует строки, поэтому порядок данных изменится. Если порядок важен, используйте другие инструменты.

Производительность

Тест на пяти файлах по 100 тысяч строк (суммарно 500 тысяч, после дедупликации — 380 тысяч):

Метод Время Дубли удалены
cat (без дедупликации) 1,2 секунды Нет
cat + sort -u 8,5 секунды Да
PowerShell Get-Content 15 секунд Нет

Проблема: эти методы работают на уровне строк, не понимая содержимое. Если номера в разных файлах записаны в разных форматах (+79001234567 и 89001234567), они не будут считаться дубликатами.

Python с библиотекой pandas

Для более интеллектуальной обработки можно использовать Python. Библиотека pandas предоставляет удобные инструменты для работы с CSV.

Простое объединение с дедупликацией

import pandas as pd

# Список файлов для объединения
files = ['файл1.csv', 'файл2.csv', 'файл3.csv']

# Читаем все файлы
dfs = [pd.read_csv(f) for f in files]

# Объединяем
merged = pd.concat(dfs, ignore_index=True)

# Удаляем дубликаты
merged_unique = merged.drop_duplicates()

# Сохраняем результат
merged_unique.to_csv('merged.csv', index=False)

# Статистика
total = len(merged)
unique = len(merged_unique)
duplicates = total - unique
print(f'Всего строк: {total}')
print(f'Уникальных: {unique}')
print(f'Дублей: {duplicates}')

Дедупликация с нормализацией номеров

Если номера записаны в разных форматах, перед дедупликацией нужно привести их к единому виду:

import pandas as pd
import re

def normalize_phone(phone):
    """Приводит номер к формату 79XXXXXXXXX"""
    if pd.isna(phone):
        return None

    # Убираем все символы кроме цифр
    phone = re.sub(r'[^\d]', '', str(phone))

    # Приводим к формату 79XXXXXXXXX
    if phone.startswith('89') and len(phone) == 11:
        phone = '7' + phone[1:]
    elif phone.startswith('9') and len(phone) == 10:
        phone = '7' + phone
    elif phone.startswith('79') and len(phone) == 11:
        pass  # уже в нужном формате
    else:
        return None  # невалидный номер

    return phone if len(phone) == 11 else None

# Читаем файлы
files = ['файл1.csv', 'файл2.csv', 'файл3.csv']
dfs = [pd.read_csv(f, header=None, names=['phone']) for f in files]
merged = pd.concat(dfs, ignore_index=True)

# Нормализуем номера
merged['phone_normalized'] = merged['phone'].apply(normalize_phone)

# Удаляем невалидные и дублирующиеся номера
merged_clean = merged.dropna(subset=['phone_normalized'])
merged_unique = merged_clean.drop_duplicates(subset=['phone_normalized'])

# Сохраняем только нормализованные номера
merged_unique[['phone_normalized']].to_csv('merged.csv', index=False, header=False)

print(f'Исходных номеров: {len(merged)}')
print(f'Валидных после нормализации: {len(merged_clean)}')
print(f'Уникальных: {len(merged_unique)}')
print(f'Удалено дублей: {len(merged_clean) - len(merged_unique)}')

Производительность pandas

Тест на тех же пяти файлах (500 тысяч строк, с разными форматами номеров):

Операция Время Использование памяти
Чтение файлов 2,1 секунды ~150 МБ
Объединение 0,3 секунды +50 МБ
Нормализация номеров 4,5 секунды +80 МБ
Дедупликация 1,2 секунды +30 МБ
Запись результата 0,8 секунды
Итого 8,9 секунды ~310 МБ

Когда использовать Python

Подходит, если:

Не подходит, если:

Базальт — специализированный инструмент

Если вы регулярно работаете с телефонными базами, удобнее использовать инструмент, заточенный под эту задачу. Базальт — десктопное приложение для работы с CSV без программирования.

Как объединить файлы в Базальте

  1. Откройте раздел «Объединить файлы»
  2. Добавьте файлы для объединения (2 или больше)
  3. Укажите название выходного файла
  4. Нажмите «Объединить файлы»
  5. Получите CSV с уникальными номерами и статистикой

Что делает Базальт автоматически

Почему автоматическая дедупликация важна

Базальт использует структуру данных Set для хранения номеров. Это даёт два критичных преимущества:

  1. O(1) сложность проверки — проверка на дубликат происходит мгновенно, даже на базах в миллионы номеров
  2. Гарантия уникальности — Set не допускает дубликатов по определению

Сравнение подходов:

Метод Сложность Время на 1 млн номеров
Ручная проверка (массив + перебор) O(n²) ~10 минут
Сортировка + сравнение соседей O(n log n) ~8 секунд
Set-based (Базальт, Python) O(n) ~3 секунды

Производительность Базальта

Тест на реальной задаче — пять файлов, суммарно 800 тысяч номеров, разные форматы (+7, 8, без префикса):

Метод Время Клики Дубли удалены Форматы нормализованы
Ручное (copy-paste) ~30 минут ~40 Нет Нет
cat + sort -u 12 секунд 0 Частично* Нет
Python + pandas 15 секунд 0 Да Да (код нужен)
Базальт 8 секунд 4 Да Да

*sort -u удаляет дубли только на уровне строк. Номера +79001234567 и 89001234567 останутся как разные записи.

Преимущества Базальта

Работа с файлами разной структуры

Частая проблема — файлы с разным количеством колонок или разным порядком данных.

Пример проблемы

Файл 1:

Имя,Телефон,Email
Иван,+79001234567,ivan@example.com

Файл 2:

Телефон,Город
89002345678,Москва

Если просто склеить эти файлы, структура сломается:

Имя,Телефон,Email
Иван,+79001234567,ivan@example.com
Телефон,Город
89002345678,Москва

Решения

Вариант 1: Извлекайте только нужную колонку перед объединением

import pandas as pd

# Читаем только колонку с телефонами
df1 = pd.read_csv('файл1.csv', usecols=['Телефон'])
df2 = pd.read_csv('файл2.csv', usecols=['Телефон'])

# Объединяем
merged = pd.concat([df1, df2], ignore_index=True)

Вариант 2: Используйте инструменты, которые парсят номера из любой структуры (например, Базальт) — они игнорируют заголовки и другие колонки, извлекая только номера.

Практические советы

  1. Всегда проверяйте количество строк до и после объединения. Формула: сумма строк всех файлов минус количество дублей = итоговое количество.
  2. Сохраняйте исходные файлы — не удаляйте их сразу после объединения, могут понадобиться для проверки.
  3. Используйте информативные названияmerged_2024-02-06_5files.csv понятнее, чем merged.csv.
  4. Документируйте источники — записывайте, какие файлы объединили, в отдельный текстовый файл.
  5. Проверяйте формат номеров — если в итоговом файле есть номера с разными префиксами (+7, 8, 7), возможно, дедупликация сработала неправильно.
  6. Учитывайте размер файлов — если суммарный размер больше 2 ГБ, Python и Excel не подойдут, используйте командную строку или специализированные инструменты.

Что выбрать для разных задач

Разовая задача, 2–3 маленьких файла без дублей — ручное копирование. Быстрее, чем разбираться с инструментами.

Работаете в Linux/macOS, файлы большие и чистые — используйте cat и sort -u. Это самый быстрый способ для стандартных CSV.

Нужна сложная логика или специфическая обработка — Python с pandas. Полный контроль над процессом, возможность добавить валидацию и трансформации.

Регулярная работа с телефонными базами, разные форматы номеров — используйте Базальт. Автоматическая нормализация, дедупликация через Set, удобный интерфейс, работает офлайн.

Ключевое отличие специализированных инструментов типа Базальта — они не просто склеивают строки, а понимают содержимое. Номера +79001234567, 8 (900) 123-45-67 и 79001234567 будут распознаны как один и тот же контакт. Это экономит деньги на рассылках и сохраняет репутацию — клиенты не получат по три одинаковых письма.