Как отсортировать CSV-файл python
Обновлено: 22.11.2024
За свою карьеру я дважды получал задание сравнить два больших файла CSV (значения, разделенные запятыми: текстовые файлы, соответствующие либо экспорту файла Excel, либо экспорту таблиц базы данных):
- В первом случае это было сравнение сделок, заключенных с помощью настроенного программного пакета в независимой стране P1, и сделок, заключенных с помощью того же программного пакета, настроенного по-разному в стране P2. Необходимо было в первую очередь перекодировать информацию, чтобы затем распознать тех, кто отсутствовал в парижской системе, и тех, кто был изменен, чтобы обновить данные парижской базы данных. Каждый файл весил около 300 Мб, а на компьютерах было около 1 Гб оперативной памяти. Ожидается, что разработка ОС будет завершена в ближайшие 3 дня максимум. (Принцип: нам нужен результат за вчерашний день со временем выполнения менее 8 часов).
- Во втором случае необходимо было согласовать потоковые файлы между двумя разными программными пакетами (старым, который нужно было вывести из эксплуатации, и новым), которые работали в условиях конкуренции, чтобы избежать регрессий. Каждый файл весил 2,5 Гб, и цель состояла в том, чтобы сравнивать их ежедневно менее чем за 2 часа. Разработка должна была начаться менее чем за две недели.
Чтобы иметь возможность сравнивать их, первый шаг (и самый сложный) состоит из сортировки двух файлов: сортируя их, мы можем уменьшить количество прочитанных строк, а также количество сравнений. К сожалению, сортировка файла требует его загрузки, а когда он большой, это усложняется.
2. Технические решения
2.1 Язык
Выбор языка сильно зависит от контекста:
Например, в этом посте мы будем использовать язык Python, чтобы получить как можно более компактный и понятный код, позволяющий вам применить метод, а затем быстро перенести его на другой язык.
2.2 Алгоритм
Выбор алгоритма будет определять производительность, а также осуществимость. Действительно, «загрузка CSV-файла» объемом 2,5 Гб в ОЗУ невозможна, если у вас нет исключительного объема памяти, запрещающего хранение файла в памяти. Сделайте несколько попыток и поэкспериментируйте, и вы обнаружите, что потребление памяти почти в 10 раз больше, когда мы вырезаем линии в векторе значений.
Вот небольшой пример:
Объединение ради победы
Вторая часть алгоритма состоит в объединении файлов 2 на 2, чтобы обеспечить сохранение сортировки. Мы будем читать по одной строке в каждом файле, сравнивать их и записывать наименьшую из них в файл результатов и заменять записанную строку следующей из того же исходного файла. Риск голода (мы израсходовали все строки в одном из двух файлов, но не в другом), тогда потребуется развить функцию сравнения, чтобы иметь возможность обрабатывать пустые строки: мы сдвигаем строку (четко определенную) в выходной файл.
5. Сортировка или ничего
Цель этой функции — организовать вырезание, а затем слияние до тех пор, пока вы не получите отсортированный файл. После вырезания мы объединим файлы 2 на 2: на каждом шаге мы делим количество файлов на 2. Мы должны продолжать, пока не будет больше одного файла. А в случае, когда на одном шаге нечетное количество файлов, будет файл для копирования с шага i на шаг i + 1.
Вот пример:
Заключение
Метод позволяет заменить проблемы с выделением памяти/управлением доступом к файлам. Таким образом, производительность будет зависеть от двух параметров:
- Время доступа к диску: избегайте использования сетевого диска для управления временными файлами, предпочитайте локальный жесткий диск.
- Количество строк при вырезании: чем меньше число, тем важнее файлы и, следовательно, тем дороже будет доступ к диску.
Необходимо откалибровать алгоритм в соответствии с используемой машиной (объемом памяти и жесткого диска) для выполнения операции и форматом CSV-файла. Это позволит сделать эффективный выбор количества строк для резки.
Для этого упражнения я буду использовать базу данных фильмов, которую скачал с Kaggle.
В этом упражнении мы будем использовать файл ratings.csv, который поставляется с базой данных фильмов.
userId | movieId | рейтинг | отметка времени< /th> | |
---|---|---|---|---|
0 | 1 | 110 | 1.0 | < td>1425941529|
1 | 1 | 147 | 4.5 | 1425942435 |
Давайте проверим размер нашего фрейма данных
Фрейм данных содержит примерно 26 миллионов записей. У каждого пользователя есть несколько записей. Давайте проверим, сколько уникальных пользователей.
Итак, в нашей базе данных 270 тысяч уникальных пользователей. Давайте посмотрим, сколько здесь уникальных фильмов.
Хорошо, представлено около 45 000 фильмов, для которых у нас есть оценки.
Давайте также проверим диапазон нашего рейтингового столбца. Для этого мы можем использовать метод description() для всего фрейма данных. Метод Describe() дает нам хорошую статистику.
userId | movieId | рейтинг | отметка времени< /th> | |
---|---|---|---|---|
число | 2.602429e+07 | 2.602429e+07 | 2,602429e+07 | 2,602429e+07 |
среднее | 1,350371e+05 | 1,584911e +04 | 3,528090e+00 | 1,171258e+09 |
станд. | 7,817620e+04 | 3,108526e+04 | 1,065443e+00 | 2,052889e+08 |
мин th> | 1.000000e+00 | 1.000000e+00 | 5.000000e-01 | 7.896520e+08 |
25% | 6,716400e+04 | 1,073000e+03 | 3,000000e+00 | 9,907545e +08 |
50% | 1,351630e+05 | 2,583000e+03 | 3,500000e+ 00 | 1,151716e+09 |
75% | 2,026930e+05 | 6,503000e+03 | 4.000000e+00 | 1.357578e+09 |
макс. | 2.708960e+05 td> | 1.762750e+05 | 5.000000e+00 | 1.501830e+09 |
Как мы видим выше, рейтинг имеет минимальное значение 0,5 и максимальное значение 5,0.
Теперь мы знаем наш фрейм данных намного лучше, давайте теперь выполним операции сортировки.
Как выполнить сортировку по значениям
Допустим, мы хотим отсортировать фильмы по рейтингу от высокого к низкому в порядке убывания.
userId | movieId | рейтинг | отметка времени< /th> | |
---|---|---|---|---|
18471899 | 191698 | 1617 | 5.0 | < td>879251202|
8646727 | 89135 | 491 | 5.0 | 860830376 |
Как мы видим выше, первые две строки теперь имеют рейтинг 5. Помните, что приведенная выше команда не сохранила данные в порядке убывания. Если мы хотим сохранить данные, используем опцию inplace=True
userId | movieId | рейтинг | отметка времени< /th> | |
---|---|---|---|---|
18471899 | 191698 | 1617 | 5.0 | < td>879251202|
8646727 | 89135 | 491 | 5.0 | 860830376 |
Для возрастания просто используйте параметр, восходящий=True, как показано ниже.
userId | movieId | рейтинг | отметка времени< /th> | |
---|---|---|---|---|
16757505 | 174227 | 3968 | 0,5 | < td>1112330388|
12103042 | 125498 | 86911 | 0,5 | 1307014797 |
Как отсортировать несколько столбцов в Pandas
Мы также можем сортировать по нескольким столбцам в Pandas, допустим, мы хотим отсортировать рейтинг от самого высокого до самого низкого, а затем от наивысшего к самому низкому идентификатору фильма.
userId | movieId | рейтинг | отметка времени< /th> | |
---|---|---|---|---|
83813 | 837 | 176271 | 5.0 | < td>1501765780|
24906715 | 258955 | 176219 | 5.0 | 1501539818 |
Как мы видим выше, рейтинг и movieId отображаются в порядке от наибольшего к наименьшему. Давайте добавим еще один столбец userId, в этом примере нет смысла сортировать movieId и userId, но для тренировки мы все равно это сделаем.
userId | movieId | рейтинг | отметка времени< /th> | |
---|---|---|---|---|
83813 | 837 | 176271 | 5.0 | < td>1501765780|
24906715 | 258955 | 176219 | 5.0 | 1501539818 |
Мы увидели, что ничего особенного не изменилось по сравнению с нашей предыдущей командой. Теперь давайте внесем небольшое изменение, отсортируем userId перед movieId и посмотрим, что получится
userId | movieId | рейтинг | отметка времени< /th> | |
---|---|---|---|---|
26024285 | 270896 | 60069 | 5.0 | < td>1257032032|
26024284 | 270896 | 58559 | 5.0 | 1257031564 |
Мы видим другой результат, чем только что произошло. Сначала мы отсортировали рейтинг, затем идентификатор пользователя. Поскольку 270896 дал более одного рейтинга фильмам, приведенный выше код сортирует movieId пользователя 270896 дальше от самого высокого к самому низкому.
Давайте рассмотрим содержательный пример. Давайте найдем среднюю оценку пользователя и отсортируем ее от самой высокой до самой низкой. Для этого запроса нам нужно будет сгруппировать по первому пользователю и применить усредненную операцию к рейтингу столбца, а затем отсортировать его по рейтингу. Давайте попробуем это.
Читайте также: