Почему Linq Бросает <T> операционный сбой, когда у меня есть неявный определенный бросок?

Вы используете .apply(), который использует простой цикл для запуска вашей функции для каждой строки. Расчет расстояния полностью выполняется в Python (geopy использует geographiclib, который, кажется, написан только на Python). Не векторизованные вычисления расстояний медленны, вам нужно векторизованное решение с использованием скомпилированного кода, как при вычислении расстояния Хаверсайна .

pyproj предлагает вычисленные по вертикали расчеты расстояний WSG84 (методы класса pyproj.Geod принимают массивы) и упаковывает библиотеку PROJ4 , то есть выполняет эти вычисления в собственном машинном коде:

from pyproj import Geod

# split out coordinates into separate columns
df[['or_lat', 'or_lon']] = pd.DataFrame(df['or'].tolist(), index=df.index)
df[['new_lat', 'new_lon']] = pd.DataFrame(df['new'].tolist(), index=df.index)

wsg84 = Geod(ellps='WGS84')
# numpy matrix of the lon / lat columns, iterable in column order
or_and_new = df[['or_lon', 'or_lat', 'new_lon', 'new_lat']].to_numpy().T
df['d2city2'] = wsg84.inv(*or_and_new)[-1] / 1000  # as km

Это синхронизируется в значительно лучшие времена:

>>> from timeit import Timer
>>> count, total = Timer(
...     "wsg84.inv(*df[['or_lon', 'or_lat', 'new_lon', 'new_lat']].to_numpy().T)[-1] / 1000",
...     'from __main__ import wsg84, df'
... ).autorange()
>>> total / count * 10 ** 3  # milliseconds
66.09873340003105

66 миллисекунд для вычисления расстояний в 100 000, неплохо!

Чтобы сделать сравнение, вот ваша версия geopy / df.apply() на том же компьютере:

>>> count, total = Timer("df.apply(lambda x: geodesic(x['or'], x['new']).km, axis=1)", 'from __main__ import geodesic, df').autorange()
>>> total / count * 10 ** 3  # milliseconds
25844.119450000107

25,8 секунды, даже не в том же поле.

19
задан Ryan Versaw 30 April 2009 в 19:51
поделиться

3 ответа

Потому что, глядя на При помощи кода через Reflector Cast не пытается учесть какие-либо неявные операторы приведения (код LINQ Cast сильно оптимизирован для особых случаев всех видов, но ничего в этом направлении) во внимание (как это делают многие языки .NET).

Не вдаваясь в размышления и другие вещи, дженерики не предлагают никакого готового способа принять во внимание такие дополнительные вещи в любом случае.

РЕДАКТИРОВАТЬ: В общем, более сложные средства, такие как неявные / явные, операторы равенства и т. Д. Не являются обычно обрабатываются общими средствами, такими как LINQ.

8
ответ дан 30 November 2019 в 05:13
поделиться

Спасибо за то, что я собирался использовать именно этот случай где-нибудь. Вы сэкономили мне кучу времени. В качестве возможного решения вашей проблемы вы могли бы вместо этого использовать ConvertAll <>, например так:

foreach (Class1 item in items.ConvertAll<Class1>((i) => (Class1)i))
{
     Console.WriteLine(item.Test1);
}

РЕДАКТИРОВАТЬ: или если вы хотите быть более явным, чтобы приведение было неявным, то это тоже работает:

foreach (Class1 item in items.ConvertAll<Class1>(i => i))
{
     Console.WriteLine(item.Test1);
}
1
ответ дан 30 November 2019 в 05:13
поделиться

Решением может быть использование здесь немного linq'инга, если вам действительно нужно такое преобразование:

List items = new List{new Class2{Test2 = 9}};
foreach (Class1 item in (from x in items select (Class1)x))
{
    Console.WriteLine(item.Test1);
}
0
ответ дан 30 November 2019 в 05:13
поделиться
Другие вопросы по тегам:

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