Преобразование SQL-запроса в Linq в Entity Query [дубликат]

Вам просто нужна функция argmax() (, теперь называемая функцией idxmax ). Это просто:

>>> import pandas
>>> import numpy as np
>>> df = pandas.DataFrame(np.random.randn(5,3),columns=['A','B','C'])
>>> df
          A         B         C
0  1.232853 -1.979459 -0.573626
1  0.140767  0.394940  1.068890
2  0.742023  1.343977 -0.579745
3  2.125299 -0.649328 -0.211692
4 -0.187253  1.908618 -1.862934
>>> df['A'].argmax()
3
>>> df['B'].argmax()
4
>>> df['C'].argmax()
1

Эта функция была обновлена ​​до имени idxmax в API Pandas, хотя с Pandas 0.16, argmax все еще существует и выполняет ту же функцию (хотя, похоже, запускается больше медленнее, чем idxmax).

Вы также можете просто использовать numpy.argmax, например numpy.argmax(df['A']) - он обеспечивает то же самое, что и любая из двух функций pandas, и появляется по крайней мере как idxmax

Ранее (как отмечалось в комментариях) оказалось, что argmax будет существовать как отдельная функция, которая обеспечивала целочисленную позицию в пределах индекс расположения строки максимального элемента. Например, если у вас есть строковые значения в качестве ярлыков индексов, например, строки 'a' through 'e', ​​вы можете знать, что max встречается в строке 4 (а не в строке 'd'). Однако в pandas 0.16 все перечисленные выше методы предоставляют только метку из Index для рассматриваемой строки, и если вы хотите, чтобы целое число позиции этой метки внутри Index, вы придется вручную (это может быть сложно теперь, когда допустимы дубликаты строк).

В общем, я думаю, что переход к idxmax -подобному поведению для всех трех подходов (argmax , который все еще существует, idxmax и numpy.argmax) является плохим, так как очень часто требуется, чтобы позиционное целочисленное местоположение было максимально, возможно, даже более распространенным, чем желание метки это позиционное расположение в пределах некоторого индекса, особенно в приложениях, где одинаковые ярлыки строк являются общими.

Например, рассмотрите эту игрушку DataFrame с двойной меткой строки:

In [19]: dfrm
Out[19]: 
          A         B         C
a  0.143693  0.653810  0.586007
b  0.623582  0.312903  0.919076
c  0.165438  0.889809  0.000967
d  0.308245  0.787776  0.571195
e  0.870068  0.935626  0.606911
f  0.037602  0.855193  0.728495
g  0.605366  0.338105  0.696460
h  0.000000  0.090814  0.963927
i  0.688343  0.188468  0.352213
i  0.879000  0.105039  0.900260

In [20]: dfrm['A'].idxmax()
Out[20]: 'i'

In [21]: dfrm.ix[dfrm['A'].idxmax()]
Out[21]: 
          A         B         C
i  0.688343  0.188468  0.352213
i  0.879000  0.105039  0.900260

So здесь наивное использование idxmax недостаточно, тогда как старая форма argmax правильно обеспечит расположение позиционного максимального ряда (в этом случае позиция 9).

Это ровно один из тех неприятных видов склонности к ошибкам поведения на динамически типизированных языках, что делает такие вещи такими неудачными и стоит победить мертвую лошадь. Если вы пишете системный код, и ваша система внезапно используется на некоторых наборах данных, которые не были очищены должным образом перед присоединением, очень легко получить дубликаты строк, особенно строковые метки, такие как идентификатор CUSIP или SEDOL для финансовых активов. Вы не можете легко использовать систему типов, чтобы помочь вам, и вы не сможете обеспечить уникальность индекса, не запуская неожиданно отсутствующих данных.

Итак, вы остались в надежде, что ваши юнит-тесты охватывают все (они этого не сделали или, скорее всего, никто не написал никаких тестов) - иначе (скорее всего) вы просто останетесь ждать, чтобы увидеть если вы случайно попали в эту ошибку во время выполнения, и в этом случае вам, вероятно, придется отказаться от работы на многие часы из базы данных, на которую вы выводили результаты, ударить головой о стену в IPython, пытаясь вручную воспроизвести проблему, наконец что idxmax может только сообщать метку максимальной строки, а затем разочаровываться в том, что никакая стандартная функция автоматически не получает позиции максимальной строки для вас, самостоятельно записывая баггирование, редактируя код и молясь, чтобы вы снова не сталкивались с проблемой.

5
задан Stu Thompson 10 January 2010 в 13:49
поделиться

1 ответ

Это должно работать:

IQueryable parentQuery = context.Parent.Select(p => new { Parent = p, ChildCount = p.Childs.Count() });

EDIT

Если вы определяете:

public class ParentModel
{
    public Task Parent { get; set; }
    public int ChildCount { get; set; }
}

, вы можете использовать

IQueryable parentQuery = context.Parent.Select(p => new ParentModel { Parent = p, ChildCount = p.Childs.Count() });

EDIT

Вы также можете сделать:

var parentQuery = context.Parent.Select(p => new { Parent = p, ChildCount = p.Childs.Count() }).ToList();
parentQuery.ForEach(p => p.Parent.ChildCount = p.ChildCount);
var result = return parentQuery.Select(p => p.Parent);

Короткие и у вас есть ваша собственность.

9
ответ дан mohsen dorparasti 21 August 2018 в 19:20
поделиться
  • 1
    Спасибо за ваш ответ, однако есть ли способ сделать это, не используя анонимный класс? – James 10 January 2010 в 13:45
  • 2
    Думал, ты собирался это сказать! Nevermind, спасибо за вашу помощь. – James 10 January 2010 в 13:53
  • 3
    Вышеупомянутое решение, но приводит к нескольким вызовам db. Как подсчет может быть получен в одном вызове для всех записей в ParentModel? – Robin Kedia 7 August 2017 в 14:36
  • 4
    @RobinKedia Это может не привести к нескольким вызовам БД в EF6. – LukLed 10 August 2017 в 08:33
Другие вопросы по тегам:

Похожие вопросы: