Pull to refresh

Comments 42

если бы еще структуру csv описали…
Так название comma separated values говорит само за себя, это простой текстовый файл, где значения разделены запятой (comma), а в данном случае точкой с запятой. Причем порядок полей не регламентирован, поэтому только глазами можно определить, где и что. Вот пример:
XXX.XXX.XXX.11;COMPANY1;992927233890;2008-06-01 19:31:35;;9;780a890bddce4248b839040046464636;16;
Вот пятое по счету поле — длительность звонка в секундах. Шестое — тот самый CallID
Пардон, шестое и седьмое, там одно поле пустое, но все равно считается.
да всё просто, в COMPANY2.csv больше записей (строк).

простой скрипт:
file1 = open("COMPANY1.csv")
file2 = open("COMPANY2.csv")
seconds1 = 0
seconds2 = 0
n1 = 0
n2 = 0
rows1 = []
rows2 = []
for row in file1.read().split("\n")[:-1]:
    rows1.append(row.split(';'))
for row in file2.read().split("\n")[:-1]:
    rows2.append(row.split(';'))
for i in range(10):
    print rows1[i][5], rows2[i][4]


выдаёт:
$ python script.py
9 10
10 10
4 5
5 5
10 11
13 14
2 3
2 3
12 13
3 5
т.е. почти в каждой записи в COMPANY2.csv больше продолжительность.
к тому же самих записей в COMPANY2 больше.
в чуть более понятном виде:

for key in rows2.keys():
    try:
        s1 += int(rows1[key])
        s2 += int(rows2[key])
     except:
        pass


получаем:
s1: 1277515
s2: 1323482
т.е. у одинаковых ключей разные значения.
ну и соответственно ключи, в которых есть разница:
for key in rows2.keys():
    try:
        if rows1[key] != rows2[key]:
            print key, rows1[key], rows2[key]
    except:
        pass

получаем:
780a0220997f43484eba250046464636 9 10
780ae213949c434816ef250046464636 33 34
780a0606a65343482c50050046464636 25 26
780a071f721c4448b85b230046464636 3 4
780a70345e8c434887aa210046464636 3 4
780a060886d0424883c8070046464636 4 5

могу предоставить полный список, если надо :)
Вот так взяли и всё испортили :-) Действительно, ларчик просто открывался, длительности одних и тех же звонков не совпадали, это в сумме и дало ту разницу. Я изначально даже и не подумал в эту сторону, настолько очевидным всё казалось, думал, ошибка в реализации подсчёта. А ошибка оказалась более фундаментальная.
А то, что количество записей разное и так было ясно из услових задачи, мы же их и искали :-)
все-равно спасибо за задачку :)
теперь можно идти спать…
И, кстати, получается, что к консенсусу нам не придти никогда с оператором, придётся использовать или наши данные или его для расчётов, т.к. такие погрешности присутствуют в каждом звонке. Жаль, что в протоколе не предусмотрена однозначная фиксация длительности сессии и только потом уже завершение звонка. Хотя опять же, её нужно реализовывать на всем участке, между каждой парой узлов и, соответственно, в каждом протоколе этого участка. Интересно, что в GSM на эту тему предусмотрено. Надо будет почитать.
ну, об этом нужно было догадаться сразу после разговора о миллионах долларов :)
Поздно, задачка простая, первый же дядя в комментариях и решил. А я что-то совсем старый стал, соображаю туго, решал долго. Придется к врачу идти, непорядок.
решать такие здачи на баше… мисье знает тольк в извращениях =)
Ну как раз на bash-е такое и решают на коленке, очень быстро и просто. Весь набор необходимых утилит существует. А если уже нужно долгосрочное, гибкое решение, да еще и с интерфейсом, то начинают расчехлять perl и т.п.
Ну я расчехлял Perl для сверки месячной статистики. Очень удобно, весь парсинг формата CDR выполняется одним регулярным выражением )
ага, как же. у тебя кода в три раза больше, чем на питоне — это о простоте. могу поспорить код на питоне ещё и сильно быстрее был написан ввиду его объектной, а не файловой ориентации.
при этом, обрати внимание, человек не остановился на достигнутом и простыми модификациями переделывал скрипт, чтобы получить какие угодно данные. а сколько подобные переделки заняли бы на баше?
Не надо мне про питон рассказывать, это мой основной язык программирования в последнее время. А в баше именно наколенная ерунда пишется на раз, когда не знаешь, что точно нужно и как это лучше получить, на ходу меняются инструменты (изначально там две другие утилиты было внутри) и т.п. Конвейеры (pipes) «решают». А вот после этого я себе уже допишу модуль в местную утилиту на Питоне для анализа таких CDR, уже зная подводные камни и алгоритм.
Работает скрипт достаточно быстро, в основном из-за join, если городить цикл, то часами будет работать :-) Кому-то удобнее такое вот «системное» программирование делать на Питоне, реально же для этого лучше подходит shell. Некоторые еще perl любят для этих целей использовать. И оно даже работает :-)
пойду заклеивать моск, ато треснул!)
excel понимает csv, кстати. со всеми вытекающими. хотя свои скрипты это конечно увлекательнее, и есть повод для поста :)
Excel понимает CSV гораздо хуже OpenOffice Calc, если уж на то пошло. Но там есть ограничение по количеству строк, например, ну и медленно считать что-то. Ни я, ни другие не могли сходу вьехать, почему разница получается, вроде бы считаем на основе второго файла, а данные не совпадают с ним же.
по сравнению с башем выбор между опенофисом и экселем кажется мне несущественным. и, судя по данным, приведенным в посте, в ограничение по количеству строк вы влезали. и единоразовый расчет может позволить себе занять несколько секунд против миллисекунд в случае потоковой башовой обработки, если на этом он сэкономит минуты, требующиеся на написание скрипта, и десятки минут, требующиеся на недоуменное почесывание головы над результатами и отладкой тех скриптов.

но в общем это конечно дело каждого, использовать готовые инструменты или расти как специалисту на подручных задачах.
Очень мне интересно, как в Excel-е проделать эту задачу быстрее, расскажите. Проделать-то нужно ровно те же операции. Использовать встроенные функции? Писать на VB?
да, использовать встроенные функции. та же сумма минут там вообще считается парой кликов мыши. все остальное — не сильно сложнее. писать на VB — не стоит, потому что опять придется отлаживать и почесывать, чего мы стремимся избежать.
Сумма минут парой кликов и считается, никто не спорит. Изначально мне нужно было найти отсутствующие в первом файле звонки. И как это сделать?
функция MATCH
Возможно. Покажите пример, я попробую на будущее. Мне проще вот так вот выдрать и сравнить, чем искать в документации правильное использование функции на массивах, вывод этого и т.п. Суть-то в том, что сравнивая и так и так и используя данные второго файла для недостающих звонков у вас все равно получится расхождение. Сейчас это кажется очевидным мне и другим, но когда я пытался найти причину, почти никто не сообразил из тех, кто обычно соображает :-)
— сводная таблица
— vlookup
— countif
— простая сортировка
вообщем вариантов мильен :)

и это, хочу заметить, вам еще повезло — увас есть уникальные id звонков — это большая удача;)

мне же приходится по тому же направлению и с теми же целями сравнивать сдры ориентируясь на время звонка, номер а, номер б и продолжительность, по причине нефиксации терминатором id звонка… и минут там на два порядка больше :)
Как мне кажется, уровень «вхождения» в электронные таблицы значительно выше для администратора, чем для пользователя. Я там ну очень редко что-то делаю, поэтому проще и привычнее это сделать в shell. Не говоря уж о гибкости.
А так да, согласен, вариантов масса, хоть на asm ;-)
Вообще странный терминатор. На самом этот и этот оригинатор очень долго отнекивался, мол, нет у него никакого CallID. Но я его убедил, что есть :-)
А вот искать по номеру А и Б уже значительно сложнее, особенно на большом количестве звонков, там уже закон больших чисел работает, на один и тот же номер идут звонки с примерной одинаковой длительностью и черта с два там определишь.
Собственно, это не весь наш диспут был, осовная задача — убедиться, что ошибаемся мы или они и в ту сторону уже отработать диспут :-)
1. По одинаковым gid`ам у нас с ними разница в 766 минут

[minutes on identical gids]
we they delta = we — they
22058 21292 766

2. А именно: разница в секундах, число раз и сумма разниц в секундах
[delta sec on identical gids]
delta count result
1 44012 44012
2 855 1710
3 16 48
4 7 28
169 1 169

3. Т.е. получаем: сумма сумм разниц в секундах и дает в итоге те самые 766 минут.
А также мы выясняем, что в среднем чье-то оборудование стабильно обманывает
другое на 1,02 секунды
[total delta in seconds and minutes]
seconds minutes averageDeltaInSeconds
45967 766 1,02396916976677

Время: 3 часа
Инструмент: SQL (access)
Все правильно. А я изначально неправильную аксиому взял за основу и, соответственно, искал ошибку не там.
А вот про обманывание тут вопрос неоднозначный. Это, скорее, погрешность округления и задержка передачи в сети.
Именно обман, ибо стабильное значение более менее и примерно около секунды.

Скорее это настройки, которые каждый выставил, как ему выгоднее (или на заводе так выставляют?).

Вам выгоднее, чтобы больше, а им меньше. Поэтому ваш трафик считается методом ceil, а ихний — floor.

Но точно не round`ом.

Сеть здесь точно не виновата — я чувствую, правда докуазать пока не могу, вернее не знаю как.
Вам еще повезло: на самом деле в csv файлах значение в одной колонке может содержать переводы строк.
Парсить csv файлы с переводами строк — вот это задача для умных.
"… что он отправили на нас меньше минут.." 0_o
идея для следующего поста — написать как работают операторы IP телефонии, чем живут, как гоняют трафик, какое ПО используют и пр.
Посмотрите доклад Кирилла Сюзева: Архитектурные особенности высоконагруженных систем в телекоме, на последнем HighLoad++
UFO just landed and posted this here
Получается, что друг друга. Собственно, в протоколе это не предусмотрено, насколько я знаю (H.323 и SIP как минимум), поэтому они спокойно записывают 5 секунд, а мы 6, т.к. у нас уже 6 насчиталось. А потом финансисты это как-то разруливают, честно говоря, технически мы ничего не делаем.
А чем собственно они регулирут такие споры? Как там можно решить спор на пару миллионов?
UFO just landed and posted this here
вспомнилась другая загадка:
Три солдата пришли на рынок покупать гуся. Бабуля объявила цену — 30 рублей. Солдаты скинулись по 10 рублей, взяли гуся и пошли довольные. У бабули вдруг проснулась совесть, она вспомнила, что её внучок сейчас тоже служит в армии и решила вернуть солдатам 5 рублей. Подозвала мальчёнку-помощника, дала ему 5 рублей и сказала, чтобы он догнал солдат и вернул им эти 5 рублей. Мальчёнка побежал, а сам думает: «Их трое, рублей пять. Дам ка я им по рублю, а два себе оставлю». Догнал, отдал им по рублю. В итого для солдат гусь обошелся по 9 рублей, то есть 9*3=27. Два рубля у мальченка. 27+2=29. Куда подевался 1 рубль?
Ха, прикольно. Я на пару минут впал в ступор пока не понял, что солдаты отдали 27 рублей, а мальчик получил 2 рубля.
примерно так 25 + 2 = 27
Sign up to leave a comment.

Articles