Для небольшой компании электронной коммерции или даже для крупного розничного продавца оптимизация складских помещений может стать важным фактором экономии затрат. Этот проект предлагает простое, но эффективное решение, помогающее определить лучшие места для хранения ваших продуктов на детальном уровне. Используя данные из магазина электронной коммерции, этот проект использует модели машинного обучения в Python для аппроксимации эффективных решений для складского хранения. Присоединяйтесь ко мне, чтобы узнать, как оптимизировать ваше складское решение для бизнеса.
Чтобы этот проект был эффективным, вы должны иметь следующие функции для работы:
- адрес
- product_type (элемент)
Остальное заберет скрипт Python. (Предполагается, что у вас есть набор данных заказов для вашего бизнеса)
df.info()
Ниже у нас есть цикл, который собирает точки широты и долготы, используемые для кластеризации в скрипте. Чтобы избежать сбоя цикла (из-за выпадения некоторых адресов), мы добавили блок try-except. Результаты добавляются в словарь. Обратите внимание, что этот процесс может занять много времени, поэтому я рекомендую настроить хранилище для ваших данных, чтобы избежать повторения процесса. По соображениям конфиденциальности мы не можем делиться своими результатами.
import pandas as pd from geopy.geocoders import Nominatim # create an instance of the geocoder geolocator = Nominatim(user_agent="geoapiExercises") # create an empty dataframe to store the results result = pd.DataFrame(columns=["Address", "Latitude", "Longitude"]) # loop over the addresses for i, address in enumerate(df.address): try: # get the location of the address location = geolocator.geocode(address) # store the address, latitude, and longitude in the dataframe result = result.append({"Address": address, "Latitude": location.latitude, "Longitude": location.longitude}, ignore_index=True) except: pass # print the results print(result)
Как я упоминал ранее, вы должны настроить хранилище данных, чтобы легко запрашивать ваши данные. Эта функция будет использоваться для перебора всех отдельных проданных товаров и будет соответствовать алгоритму k-средних для получения центроидов.
def lat_long(): query = """select distinct(item) from OCF.distances""" items = pd.read_sql(query, con = engine_ocf) center = [] for i in range(0,len(items)): query = """SELECT address_1, gender, suspected_income, zip, zestimate, city, livingArea, item, price, quantity, fulfilled, purchase, Date, Latitude, Longitude FROM OCF.orderss join OCF.coordinates on OCF.orderss.address = OCF.coordinates.address where item = '{}'""".format(items.item[i]) center.append(pd.read_sql(query, con = engine_ocf)) query = pd.concat(center) return query
Эти две функции работают вместе для вычисления расстояния между точками. Первая функция, haversine_distance, вычисляет расстояние по формуле гаверсинуса, которая учитывает угловатость земли и возвращает результат в километрах. Вторая функция, calculate_distance_between_lists, использует функцию haversine_distance в цикле для создания списка расстояний между точками в данных.
import math def haversine_distance(lat1, lon1, lat2, lon2): # convert decimal degrees to radians lat1, lon1, lat2, lon2 = map(math.radians, [lat1, lon1, lat2, lon2]) # haversine formula dlat = lat2 - lat1 dlon = lon2 - lon1 a = math.sin(dlat/2)**2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon/2)**2 c = 2 * math.asin(math.sqrt(a)) # Earth radius in kilometers km = 6371 * c return km def calculate_distance_between_lists(latitudes1, longitudes1, latitudes2, longitudes2): if len(latitudes1) != len(longitudes1) or len(latitudes2) != len(longitudes2): raise ValueError("The length of the latitude and longitude lists must be the same.") if len(latitudes1) != len(latitudes2): raise ValueError("The length of the two latitude lists must be the same.") distances = [] for lat1, lon1, lat2, lon2 in zip(latitudes1, longitudes1, latitudes2, longitudes2): distances.append(haversine_distance(lat1, lon1, lat2, lon2)) return distances
Следующим шагом является создание алгоритма, который находит центроиды с помощью кластеризации K-средних, метода неконтролируемого машинного обучения. Для выполнения этого шага в вашей среде Python должен быть установлен Scikit-learn (sklearn). Под функцией find_k_means_centroids мы создали цикл, который перебирает фрейм данных, хранящийся в функции lat_long(). Затем результаты сохраняются в словаре centroids_1, который мы будем использовать для построения и определения оптимальных складов в этом районе.
import numpy as np from sklearn.cluster import KMeans def find_k_means_centroids(data, k): # Fit the KMeans model to the data kmeans = KMeans(n_clusters=k, random_state=0).fit(data) # Get the cluster centroids centroids = kmeans.cluster_centers_ return centroids centriods_1 = { "item" : [], "Latitude": [], "Longitude": []} for i in lat_long().item.unique(): df = lat_long()[lat_long()['item'] == i] try: for k in range(2, 3): centroids = find_k_means_centroids(df[['Latitude', 'Longitude']].values, k) centriods_1["item"].append(i) centriods_1["Latitude"].append(centroids[0][0]) centriods_1["Longitude"].append(centroids[0][1]) centriods_1["item"].append(i) centriods_1["Latitude"].append(centroids[1][0]) centriods_1["Longitude"].append(centroids[1][1]) print("Centroids for k =", df.item.iloc[k]) print(centroids) print("\n") except Exception as e: centriods_1['Latitude'].append(float('nan')) centriods_1['Longitude'].append(float('nan')) centriods_1['item'].append(float('nan'))
Далее мы хотим визуализировать и увидеть, где центроиды встают на свои места.
## import plotly.express as px import pandas as pd import plotly.express as px # Create the scatter plot fig = px.scatter_mapbox(centroids_df, lat="Latitude", lon="Longitude", color="item", color_discrete_sequence=["red", "green", "blue", "yellow", "purple", "cyan", "orange", "pink","Magenta","Maroon","Violet","Purple", "Olive"], mapbox_style="carto-positron", size_max=45,zoom=50) # Add the map layout fig.update_layout(mapbox_center = {"lat": 37.0902, "lon": -95.7129}, mapbox=dict(center=dict(lat=37.0902, lon=-95.7129), zoom=3)) legend=dict(x=0, y=1, traceorder="normal", font=dict(size=4)) # Show the plot fig.show()
Сравнение результатов центроида с отображением всех совершенных покупок.
Затем нам нужно собрать склады в Соединенных Штатах, для этого я использовал центры выполнения Amazon в качестве наших выбранных складов.
Для центров выполнения вы можете найти их здесь и собрать данные с помощью простого pd.read_html(ссылка)[0]:
def distances_to_fba(): from math import radians, sin, cos, sqrt, atan2 data = centroids_df # Convert latitude and longitude columns to radians data['latitude'] = centroids_df['Latitude'].apply(radians) data['longitude'] = centroids_df['Longitude'].apply(radians) fba['latitude'] = fba['Latitude'].apply(radians) fba['longitude'] = fba['Longitude'].apply(radians) # Define the Earth's radius (mean radius = 6,371km) R = 6371 # Initialize an empty list to store the distances distances = {'distances' : [], 'Amazon Address': [], 'product': [], 'Longitude' : [], 'Latitude' : [] } # Loop through each row in df1 for index1, row1 in data.iterrows(): lat1 = row1['latitude'] lon1 = row1['longitude'] product = row1['item'] # Loop through each row in df2 for index2, row2 in fba.iterrows(): lat2 = row2['latitude'] lon2 = row2['longitude'] # Calculate the Haversine distance between two points a = sin((lat2-lat1)/2)**2 + cos(lat1) * cos(lat2) * sin((lon2-lon1)/2)**2 c = 2 * atan2(sqrt(a), sqrt(1-a)) d = R * c # Append the distance to the list distances['distances'].append(d) distances['Amazon Address'].append(row2['Address']) distances['product'].append(product) distances['Latitude'].append(row2['Latitude']) distances['Longitude'].append(row2['Longitude']) df = pd.DataFrame(distances) return df # Convert the distances list to a numpy array #distances = np.array(distances)
Последний шаг в этом проекте — выяснить, где разместить ваши продукты. Для этого я создал цикл, который перебирает расстояния в порядке возрастания и получает для каждого продукта голову кадра.
Best_locations = {'product': [], 'Amazon Address': [], 'distances' : [], 'Longitude' : [], 'Latitude' : []} for i in list(items.item): try: Best_locations['product'].append(distances_to_fba()[distances_to_fba()['product'] ==str(i)].sort_values(by="distances", ascending=True).head(1)['product'].unique()[0] ) Best_locations['Amazon Address'].append(distances_to_fba()[distances_to_fba()['product'] ==str(i)].sort_values(by="distances", ascending=True).head(1)['Amazon Address'].unique()[0]) Best_locations['distances'].append(distances_to_fba()[distances_to_fba()['product'] ==str(i)].sort_values(by="distances", ascending=True).head(1)['distances'].unique()[0]) Best_locations['Latitude'].append(distances_to_fba()[distances_to_fba()['product'] ==str(i)].sort_values(by="distances", ascending=True).head(1)['Latitude'].unique()[0]) Best_locations['Longitude'].append(distances_to_fba()[distances_to_fba()['product'] ==str(i)].sort_values(by="distances", ascending=True).head(1)['Longitude'].unique()[0]) except: pass pd.DataFrame(Best_locations)
Конечным результатом являются рекомендуемые места для хранения продуктов, как показано ниже.
Если вам понравилось читать об этом проекте или вы даже использовали часть кода в своей работе, свяжитесь со мной в Linkedin и ознакомьтесь с некоторыми другими моими работами на Github. В настоящее время ищу свою первую роль в науке о данных, так как я недавно закончила магистратуру. в аналитике данных. Ссылки ниже!
https://www.linkedin.com/in/tylerbrownpsu/