Вы должны сгруппировать оба объекта, которые хотите сохранить, а затем сосчитать тот, в котором вы хотите найти вхождения. Вот пример входного файла:
Brand Model
Acura RDX
Acura RDX
Acura RDX
Acura RDX
Acura RDX
Acura RDX
Acura RDX
Acura RDX
Acura RDX
Acura RDX
Beach Baby
Beach Baby
Beach Baby
Beach Baby
Beach Baby
Beach Baby
Beach Baby
Beach Baby
Beach Baby
Beach Baby
BMW 320i
BMW 320i
BMW 320i
BMW 320i
BMW 320i
BMW 320i
BMW 320i
BMW 550i
BMW 550i
BMW 550i
BMW 550i
BMW 550i
BMW 550i
BMW 550i
Cadillac Escalade
Cadillac Escalade
Cadillac Escalade
Chana Cargo
Chana Cargo
Chana Cargo
Chana Cargo
Chana Cargo
Chana Cargo
Chana Cargo
Chana Cargo
Chana Cargo
Chana Cargo
Chana Cargo
Chana Cargo
Простые панды один вкладыш:
df = pd.read_table('fun.txt', header=0)
print(df.groupby(['Brand','Model'])['Model'].agg(['count']))
И вывод:
count
Brand Model
Acura RDX 10
BMW 320i 7
550i 7
Beach Baby 10
Cadillac Escalade 3
Chana Cargo 12
Если вы хотите отсортировать значения по частоте (от наибольшего к наименьшему) и оставьте только самое большое, измените однострочник на:
groupby_df = (df.groupby(['Brand','Model'])['Model'].agg(['count']).sort_values(by='count', ascending=False).reset_index().drop_duplicates('Brand', keep='first'))
, чтобы получить:
Brand Model count
0 Chana Cargo 12
1 Acura RDX 10
2 Beach Baby 10
3 BMW 320i 7
5 Cadillac Escalade 3
По крайней мере, вы сформулировали вопрос с правильной точки зрения =)
Обычными причинами использования генератора кода являются производительность и согласованность, поскольку они предполагают, что решение последовательной и повторяющейся проблемы состоит в добавлении большего количества кода на него. Я бы сказал, что каждый раз, когда вы думаете о генерации кода, посмотрите, почему вы генерируете код, и посмотрите, можете ли вы решить проблему другими способами.
Классическим примером этого является доступ к данным; вы можете сгенерировать 250 классов (по 1 для каждой таблицы в схеме), эффективно создав решение для шлюза таблиц, или вы можете создать что-то более похожее на модель предметной области и использовать NHibernate / ActiveRecord / LightSpeed / [выберите свой orm] для отображения богатой модели предметной области в базу данных.
Хотя и ручное решение, и ORM являются эффективными генераторами кода, основное различие заключается в том, когда код генерируется. В ORM это неявный шаг, который происходит во время выполнения и, следовательно, является односторонним по своей природе. Решение, созданное вручную, требует явного шага для генерации кода во время разработки и вероятности того, что сгенерированные классы потребуют настройки в какой-то момент, что создаст проблемы при повторной генерации кода. Явный шаг, который должен произойти во время разработки, вносит трение в процесс разработки и часто приводит к коду, который нарушает DRY (хотя некоторые утверждают, что сгенерированный код никогда не может нарушать DRY).
Другая причина рекламирования генерации кода связана с миром MDA / MDE (Model Driven Architecture / Engineering).Я не придаю этому большого значения, но вместо того, чтобы приводить ряд плохо выраженных аргументов, я просто собираюсь привлечь кого-нибудь еще - http://www.infoq.com/articles/8-reasons -why-MDE-fails .
Генерация кода IMHO - единственное решение в чрезвычайно узком наборе проблем, и всякий раз, когда вы его рассматриваете, вам, вероятно, следует еще раз взглянуть на реальную проблему, которую вы пытаетесь решить, и посмотреть, есть ли там это лучшее решение.
Одним из типов генерации кода, действительно повышающим продуктивность, является «генерация микрокода», когда использование макросов и шаблонов позволяет разработчику генерировать новый код непосредственно в среде IDE и вводить / вводить свой путь через заполнители (например, пространство имен / имя класса и т. д.). Такая генерация кода - это функция resharper, и я интенсивно использую ее каждый день. Причина того, что микрогенерация выигрывает там, где большинство крупномасштабных генераций кода терпит неудачу, заключается в том, что сгенерированный код не привязан к какому-либо другому ресурсу, который должен быть синхронизирован, и поэтому, как только код сгенерирован, он такой же, как и весь другой код в решение.
@John
Перенос создания "базовых классов" из среды IDE в xml / dsl часто наблюдается при большой разработке. Классическим примером может быть попытка разработчиков преобразовать базу данных в модель предметной области.Если генератор кода не очень хорошо написан, он просто создает дополнительную нагрузку на разработчика, поскольку каждый раз, когда им нужно обновить модель предметной области, им придется либо переключать контекст и обновлять xml / dsl, либо расширять модель предметной области. а затем перенесите эти изменения обратно в xml / dsl (эффективно выполняя работу дважды).
Есть некоторые генераторы кода, которые очень хорошо работают в этой области (дизайнер LightSpeed - единственный, о котором я могу думать), выступая в качестве движка для поверхности дизайна, но часто эти генераторы кода генерируют ужасные код, который невозможно поддерживать (например, поверхности проектирования winforms / webforms, поверхность проектирования EF1) и, следовательно, быстро сводит на нет любые преимущества производительности, полученные от использования генератора кода в первую очередь.
Я на самом деле добавляю последние штрихи к генератору кода, который я использую для проекта, на который меня наняли. У нас есть огромные XML-файлы определений, и за несколько дней работы я смог создать более 500 классов C #. Если я хочу добавить функциональность ко всем классам, скажем, я хочу добавить атрибут ко всем свойствам. Я просто добавляю его в мой код-генератор, нажимаю go и бам! Я сделал.
Это действительно хорошо, правда.
Все говорят здесь о простой генерации кода, но как насчет генерации кода на основе моделей (например, MDSD или DSM)? Это поможет вам выйти за пределы простых ORM / участников-участников / генераторов шаблонов и перейти к генерации кода высокоуровневых концепций для вашей проблемной области.
Это не продуктивно для одноразовых проектов, но даже для них разработка на основе моделей вводит дополнительную дисциплину, лучшее понимание используемых решений и, как правило, лучший путь развития.
Подобно тому, как 3GL и ООП обеспечили увеличение абстракции за счет генерации большого количества кода сборки на основе спецификации более высокого уровня, разработка на основе моделей позволяет нам снова повысить уровень абстракции с еще одним повышением производительности.
MetaEdit + от MetaCase (для взрослых) и ABSE от Isomeris (мой проект, в альфа-версии, информация на http://www.abse.info ) - две технологии, находящиеся на переднем крае генерации кода на основе моделей. .
Что действительно нужно, так это изменение мышления (как ООП, необходимого в 90-х годах) ...
Как насчет примера хорошего использования генератора кода?
При этом используются шаблоны t4 (генератор кода, встроенный в Visual Studio) для генерации сжатых CSS из файлов .less: http://haacked.com/archive/2009/12/02/t4- template-for-less-css.aspx
По сути, он позволяет вам определять переменные, реальное наследование и даже поведение в ваших таблицах стилей, а затем создавать нормальный css из этого во время компиляции.
Генератор кода полезен, если:
Стоимость написания и обслуживания генератора кода меньше, чем стоимость написания и поддержки повторения, которое он заменяет.
Согласованность, полученная при использовании генератора кода, уменьшит количество ошибок до такой степени, которая делает это полезным.
Дополнительная проблема отладки сгенерированного кода не сделает отладку недостаточно эффективной, чтобы перевесить преимущества от 1 и 2.
Каноническим примером этого является доступ к данным, но у меня есть другой пример. Я работал над системой обмена сообщениями, которая связывается через последовательный порт, сокеты и т. Д., И я обнаружил, что мне постоянно приходится писать такие классы снова и снова:
public class FooMessage
{
public FooMessage()
{
}
public FooMessage(int bar, string baz, DateTime blah)
{
this.Bar = bar;
this.Baz = baz;
this.Blah = blah;
}
public void Read(BinaryReader reader)
{
this.Bar = reader.ReadInt32();
this.Baz = Encoding.ASCII.GetString(reader.ReadBytes(30));
this.Blah = new DateTime(reader.ReadInt16(), reader.ReadByte(),
reader.ReadByte());
}
public void Write(BinaryWriter writer)
{
writer.Write(this.Bar);
writer.Write(Encoding.ASCII.GetBytes(
this.Baz.PadRight(30).Substring(0, 30)));
writer.Write((Int16)this.Blah.Year);
writer.Write((byte)this.Blah.Month);
writer.Write((byte)this.Blah.Day);
}
public int Bar { get; set; }
public string Baz { get; set; }
public DateTime Blah { get; set; }
}
Попробуйте представить, если вы будет, написав этот код для не менее 300 различных типов сообщений. Один и тот же скучный, утомительный, подверженный ошибкам код пишется снова и снова. Мне удалось написать примерно 3 из них, прежде чем я решил, что мне будет проще написать генератор кода, и я сделал это.
Я не буду публиковать код code-gen, это много загадочных вещей в CodeDom, но суть в том, что мне удалось сжать всю систему до одного XML-файла:
<Messages>
<Message ID="12345" Name="Foo">
<ByteField Name="Bar"/>
<TextField Name="Baz" Length="30"/>
<DateTimeField Name="Blah" Precision="Day"/>
</Message>
(More messages)
</Messages>
Насколько это проще? (Риторический вопрос.) Я мог наконец дышать. Я даже добавил несколько наворотов, чтобы он мог генерировать «прокси», и я мог написать такой код:
var p = new MyMessagingProtocol(...);
SetFooResult result = p.SetFoo(3, "Hello", DateTime.Today);
В конце я бы сказал, что это спасло меня от написания хороших 7500 строк. кода и превратил 3-недельное задание в 3-дневное задание (ну, плюс пара дней, необходимых для написания кода).
Вывод: генерация кода подходит только для относительно небольшого числа проблем, но когда вы сможете ее использовать, она спасет ваше здравомыслие .
Действительно, когда вы используете практически любой язык программирования, вы используете «генератор кода» (за исключением ассемблера или машинного кода). Я часто пишу маленькие 200-строчные сценарии, которые запускают несколько тысяч строк C. это также программное обеспечение, которое вы можете получить, которое помогает генерировать определенные типы кода (например, yacc и lex используются для генерации синтаксических анализаторов для создания языков программирования.)
Здесь ключ к тому, чтобы думать о входе вашего генератора кода как реальный исходный код, и думайте о том, что он выделяет, как о части процесса сборки. В этом случае вы пишете на языке более высокого уровня с меньшим количеством фактических строк кода, чтобы иметь дело.
Например, вот очень длинный и утомительный файл, который я (не) написал как часть моей работы по модификации игрового движка CRX на базе Quake2. Он берет целочисленные значения всех # определенных констант из двух заголовков и превращает их в «cvars» (переменные для игровой консоли.)
http: //meliaserlow.dyndns. tv: 8000 / alienarena / lua_source / game / cvar_constants.c
Вот короткий сценарий Bash, сгенерировавший этот код во время компиляции:
http: // meliaserlow.dyndns.tv:8000/alienarena/lua_source/autogen/constant_cvars.sh
Теперь, что бы вы предпочли сохранить? Они оба эквивалентны с точки зрения того, что они описывают, но один из них гораздо длиннее и раздражает в обращении.
В любое время, когда вам нужно создать большое количество повторяющегося шаблонного кода, генератор кода - это то, что вам нужно. В последний раз я использовал генератор кода при создании пользовательского уровня доступа к данным для проекта, где был создан каркас для различных действий CRUD на основе объектной модели. Вместо того, чтобы вручную кодировать все эти классы, я собрал генератор кода на основе шаблонов (используя StringTemplate ), чтобы сделать его для меня. Преимущества этой процедуры были:
Ну, это либо:
Итак, генератор кода дает вам:
Прекрасные примеры:
Шаблоны Linq-to-SQL T4 от Damien Guard для создания одного отдельного файла на класс в вашей модели базы данных, используя самый лучший секрет Visual Studio 2008 - шаблоны T4
PLINQO - то же самое, но для генератора Кодесмита
и бесчисленное множество .....
Для доменных или многоуровневых приложений генерация кода является отличным способом создания исходной модели или уровня доступа к данным. Он может произвести 250 классов сущностей за 30 секунд (или в моем случае 750 классов за 5 минут). Это оставляет программисту возможность сосредоточиться на улучшении модели с помощью отношений, бизнес-правил или получения представлений в MVC.
Ключевым моментом здесь является, когда я говорю исходную модель. Если для поддержки кода вы полагаетесь на генерацию кода, то настоящая работа выполняется в шаблонах. (Как сказал Макс Э.) И остерегайтесь этого, потому что существует риск и сложность в поддержке кода на основе шаблонов.
Если вы просто хотите, чтобы слой данных был «автоматически создан», чтобы вы могли «заставить графический интерфейс работать за 2 дня», то я бы предложил использовать продукт / набор инструментов, ориентированный на управляемый или двухуровневый сценарий приложения.
И, наконец, имейте в виду, что «garbage in = garbage out». Если весь ваш уровень данных однороден и не абстрагируется от базы данных, пожалуйста, спросите себя, зачем вам вообще нужен уровень данных. (Если вам не нужно выглядеть продуктивно :))
Если с генератором кода вы также намереваетесь использовать фрагменты, попробуйте разницу между вводом ctor + TAB и написанием конструктора каждый раз в ваших классах. Или проверьте, сколько времени вы зарабатываете, используя фрагмент для создания оператора switch, связанного с перечислением со многими значениями.
Использование построителей графического интерфейса, которые генерируют для вас код, является обычной практикой. Благодаря этому вам не нужно вручную создавать все виджеты. Вы просто перетаскиваете их и используете сгенерированный код. Для простых виджетов это действительно экономит время (я часто использовал это для wxWidgets).
Если вам платят LOC и вы работаете на людей, которые не понимают, что такое генерация кода, это имеет большой смысл. Это не шутка, кстати - я работал с несколькими программистами, которые использовали эту технику именно для этой цели. Формально LOC больше никому не платят (во всяком случае, мне об этом известно), но от программистов обычно ожидают продуктивности, а выдача больших объемов кода может заставить кого-то выглядеть продуктивным.
В качестве лишь слегка касательного момента, я думаю, это также объясняет тенденцию некоторых программистов разбивать единую логическую единицу кода на как можно большее количество различных классов (вы когда-нибудь получали в наследство проект с классами LastName
, FirstName
и MiddleInitial
?).
Вот некоторая ересь:
Если задача настолько глупая, что ее можно автоматизировать во время написания программы (т.е. исходный код может быть сгенерирован скриптом из, скажем, XML ), то то же самое можно сделать во время выполнения (т.е. некоторое представление этого XML может быть интерпретировано во время выполнения) или с помощью некоторого метапрограммирования. Таким образом, по сути, программист был ленив, не пытался решить настоящую проблему, но выбрал простой выход и написал генератор кода. В Java / C # посмотрите на отражение, а в C ++ посмотрите на шаблоны
Существует множество вариантов использования генерации кода.
Написание кода на знакомом языке и генерация кода для другого целевого языка.
Java -> Javascript
C# -> Objective-C
Написание кода на более высоком уровне абстракции.
Автоматизация повторяющихся задач.
Игнорируя все предвзятые представления о генерации кода, можно сказать, что это перевод одного представления (обычно более высокого уровня) в другое (обычно более низкого уровня). Учитывая это определение, можно сказать, что это очень мощный инструмент.
Современное состояние языков программирования ни в коем случае не раскрыло весь свой потенциал и никогда не раскроет. Мы всегда будем абстрагироваться, чтобы перейти на более высокий уровень, чем тот, на котором мы находимся сегодня. Генерация кода - это то, что поможет нам достичь этого. Мы можем либо положиться на создателей языка, чтобы они создали эту абстракцию для нас, либо сделать это сами. Сегодня языки достаточно сложны, чтобы позволить любому сделать это легко.