Наконец, у меня есть кое-что быстрее, чем первоначальный вопрос.
Во-первых, я создал многоугольник, описывающий ограничивающую рамку, используя информацию из набора данных морских районов МГО
# Create a bbox polygon
iho_df['bbox'] = iho_df.apply(lambda x: Polygon([(x['min_X'], x['min_Y']), (x['min_X'], x['max_Y']), (x['max_X'], x['max_Y']), (x['max_X'], x['min_Y'])]), axis=1)
Затем, Я изменил функцию, чтобы сначала посмотреть на bbox (что намного быстрее, чем геометрия, поскольку это просто прямоугольник). Когда точка попадает в несколько ящиков (для граничащих морей), тогда и только тогда она смотрит на начальные многоугольники, чтобы найти правильное имя моря среди совпадающих ящиков (а не во всех многоугольниках).
# Function that checks and maps lon lat pair with sea name
def get_seaname(long,lat):
pnt = Point(long,lat)
names = []
# Check within each bbox first to note the polygons to look at
for i,j in enumerate(iho_df.bbox):
if pnt.within(j):
names.append(iho_df.NAME.iloc[i])
# Return nan for no return
if len(names)==0:
return np.nan
# Return the single name of the sea
elif len(names)==1:
return names[0]
# Run the pnt.within() only for the polygons within the collected sea names
else:
limitizez_df = iho_df[iho_df['NAME'].isin(names)].reset_index(drop=True)
for k,n in enumerate(limitizez_df.geometry):
if pnt.within(n):
return limitizez_df.NAME.iloc[k]
Этот момент значительно сократил время. Чтобы еще больше увеличить его, я использовал многопроцессорность для распараллеливания ядра процессора. Идея была взята из другого поста StackOverflow, который я сейчас не помню, но здесь приведен код.
import multiprocessing as mp
# Function that parallelizes the apply function among the cores of the CPU
def parallelize_dataframe(df, func, n_cores):
df_split = np.array_split(df, n_cores)
pool = Pool(n_cores)
df = pd.concat(pool.map(func, df_split))
pool.close()
pool.join()
return df
# Function that adds a sea_name column in the main dataframe
def add_features(df):
# Apply the function
df['sea_name'] = df.apply(lambda x: get_seaname(x['Position Longitude'], x['Position Latitude']), axis=1)
return df
Наконец, вместо использования функции apply для get_seaname (), я использовал ее для parallelize_dataframe () функция для запуска на всех доступных ядрах процессора:
### Apply the above function to the dataframe
ships_df = parallelize_dataframe(ships_df, add_features, n_cores=mp.cpu_count())
Надеюсь, мое решение поможет и другим людям!