Image

Создание современной панели инструментов с помощью Python и Gradio

Анализ данных стал проще

Делиться

eafe954f3b38dc6470b99153a9d0a1b9

Это вторая статья из короткой серии, посвященной разработке панелей управления данными с использованием новейших инструментов разработки графических интерфейсов на основе Python: Streamlit, Gradio и Taipy.

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

В первой части этой серии я создал версию панели мониторинга Streamlit, которая извлекает свои данные из локальной базы данных PostgreSQL. Вы можете просмотреть эту статью здесь.

На этот раз мы рассмотрим использование библиотеки Gradio.

Данные для этой панели мониторинга будут храниться в локальном CSV-файле, а Pandas станет нашим основным механизмом обработки данных.

Если вы хотите увидеть быструю демонстрацию приложения, я развернул его в Hugging Face Spaces. Вы можете запустить его, используя ссылку ниже, но учтите, что два всплывающих окна выбора даты не работают из-за известной ошибки в среде Hugging Face. Это касается только приложений, развернутых на HF, вы по-прежнему можете изменять даты вручную. Локальный запуск приложения работает нормально и не имеет этой проблемы.

Демонстрация панели управления на HuggingFace

Что такое Градио?

Gradio — это пакет Python с открытым исходным кодом, который упрощает процесс создания демонстраций или веб-приложений для моделей машинного обучения, API или любой функции Python. С его помощью вы можете создавать демонстрации или веб-приложения без необходимости иметь опыт работы с JavaScript, CSS или веб-хостингом. Написав всего несколько строк кода Python, вы можете раскрыть всю мощь Gradio и без проблем продемонстрировать свои модели машинного обучения более широкой аудитории.

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

Этот пакет Python с открытым исходным кодом поможет вам сократить разрыв между вашим опытом в области машинного обучения и более широкой аудиторией, сделав ваши модели доступными и применимыми на практике.

Что мы будем разрабатывать

Мы разрабатываем панель управления данными. Нашими исходными данными будет один CSV-файл, содержащий 100 000 синтетических записей о продажах.

Фактический источник данных не так уж и важен. Это может быть текстовый файл, файл Excel, SQLite или любая база данных, к которой вы можете подключиться.

Вот как будет выглядеть наша окончательная панель инструментов.

3dfed4b47ea780cd3a2f26b889804d39

Состоит из четырех основных разделов.

  • Верхняя строка позволяет пользователю выбрать конкретные даты начала и окончания и/или категории продуктов с помощью выбора дат и раскрывающегося списка соответственно.
  • Вторая строка — Ключевые показатели — показывает сводку верхнего уровня выбранных данных.
  • Раздел «Визуализация» позволяет пользователю выбрать один из трех графиков для отображения входного набора данных.
  • Раздел необработанных данных является именно тем, чем он себя называет. Это табличное представление выбранных данных фактически показывает снимок базового файла данных CSV.

Использовать панель мониторинга просто. Сначала отображается статистика по всему набору данных. Затем пользователь может сузить фокус данных, используя три поля фильтра в верхней части дисплея. Графики, ключевые показатели и разделы необработанных данных динамически обновляются, чтобы отражать выбор пользователя в полях фильтра.

Базовые данные

Как уже упоминалось, исходные данные панели мониторинга содержатся в одном файле со значениями, разделенными запятыми (CSV). Данные состоят из 100 000 синтетических записей, связанных с продажами. Вот первые десять записей файла, чтобы дать вам представление о том, как он выглядит.

+———-+————+————+—————-+————-+————+————+———+———————+ | order_id | order_date | customer_id| customer_name | product_id | product_names | categories | quantity | price | total | +———-+————+————+—————-+————-+————+————+———-+———————+ | 0 | 08.01.2022 | 245 | Клиент_884 | 201 | Смартфон | Электроника| 3 | 90,02 | 270,06 | | 1 | 19.02.2022 | 701 | Клиент_1672 | 205 | Принтер | Электроника| 6 | 12,74 | 76,44 | | 2 | 01.01.2017 | 184 | Customer_21720 | 208 | Блокнот | Канцелярские принадлежности | 8 | 48,35 | 386,8 | | 3 | 09/03/2013 | 275 | Customer_23770 | 200 | Ноутбук | Электроника| 3 | 74,85 | 224,55 | | 4 | 23/04/2022 | 960 | Customer_23790 | 210 | Шкаф | Офис | 6 | 53,77 | 322,62 | | 5 | 10/07/2019 | 197 | Customer_25587 | 202 | Письменный стол | Офис | 3 | 47,17 | 141,51 | | 6 | 12/11/2014 | 510 | Customer_6912 | 204 | Монитор | Электроника| 5 | 22,5 | 112,5 | | 7 | 12/07/2016 | 150 | Customer_17761 | 200 | Ноутбук | Электроника| 9 | 49,33 | 443,97 | | 8 | 12/11/2016 | 997 | Customer_23801 | 209 | Кофеварка | Электроника| 7 | 47,22 | 330,54 | | 9 | 23/01/2017 | 151 | Customer_30325 | 207 | Ручка | Канцелярские принадлежности | 6 | 3,5 | 21 | +———-+————+————+—————-+—————+————+———-+———————+

А вот код Python, который вы можете использовать для генерации похожего набора данных. Убедитесь, что библиотеки NumPy и Pandas установлены первыми.

# сгенерировать файл CSV размером 100 КБ # импортировать polars как pl import numpy как np from datetime import datetime, timedelta def generate(nrows: int, filename: str): names = np.asarray( [ «Ноутбук», «Смартфон», «Стол», «Стул», «Монитор», «Принтер», «Бумага», «Ручка», «Блокнот», «Кофеварка», «Шкаф», «Пластиковые стаканчики», ] ) categories = np.asarray( [ «Электроника», «Электроника», «Офис», «Офис», «Электроника», «Электроника», «Канцелярские принадлежности», «Канцелярские принадлежности», «Канцелярские принадлежности», «Электроника», «Офис», «Разное», ] ) product_id = np.random.randint(len(names), size=nrows) quantity = np.random.randint(1, 11, size=nrows) price = np.random.randint(199, 10000, size=nrows) / 100 # Генерация случайных дат между 2010-01-01 и 2023-12-31 start_date = datetime(2010, 1, 1) end_date = datetime(2023, 12, 31) date_range = (end_date — start_date).days # Создание случайных дат в виде np.array и преобразование в строковый формат order_dates = np.array([(start_date + timedelta(days=np.random.randint(0, date_range))).strftime('%Y-%m-%d') for _ in range(nrows)]) # Определение столбцов columns = { «order_id»: np.arange(nrows), «order_date»: order_dates, «customer_id»: np.random.randint(100, 1000, size=nrows), «customer_name»: [f»Customer_{i}» for i in np.random.randint(2**15, size=nrows)], «product_id»: product_id + 200, «product_names»: names[product_id], «categories»: categories[product_id], «quantity»: quantity, «price»: price, «total»: price * quantity, } # Создать Polars DataFrame и записать в CSV с явным разделителем df = pl.DataFrame(columns) df.write_csv(filename, Separater=',',include_header=True) # Обеспечить использование запятой в качестве разделителя # Сгенерировать 100 000 строк данных со случайной order_date и сохранить в CSV generate(100_000, «/mnt/d/sales_data/sales_data.csv»)

Установка и использование Gradio

Установка Gradio проста с помощью pip , но для кодирования лучше всего настроить отдельную среду Python для всей вашей работы. Я использую Miniconda для этой цели, но вы можете использовать любой метод, который подходит вашей рабочей практике.

Если вы хотите использовать Conda и у вас его еще нет, вам необходимо сначала установить Miniconda (рекомендуется) или Anaconda.

Обратите внимание, что на момент написания статьи для корректной работы Gradio требовалась как минимум установленная версия Python 3.8.

После создания среды переключитесь на нее с помощью команды «activate» , а затем запустите «pip install», чтобы установить необходимые библиотеки Python.

#создаем нашу тестовую среду (базу) C:Usersthoma>conda create -n gradio_dashboard python=3.12 -y # Теперь активируем ее (базу) C:Usersthoma>conda activate gradio_dashboard # Устанавливаем библиотеки python и т. д. (gradio_dashboard) C:Usersthoma>pip install gradio pandas matplotlib cachetools

Основные различия между Streamlit и Gradio

Как я продемонстрирую в этой статье, можно создавать очень похожие панели мониторинга данных с помощью Streamlit и Gradio. Однако их этос отличается в нескольких ключевых аспектах.

Фокус

  • Gradio специализируется на создании интерфейсов для моделей машинного обучения, в то время как Streamlit больше предназначен для приложений обработки данных общего назначения и визуализации.

Простота использования

  • Gradio известен своей простотой и возможностями быстрого прототипирования, что делает его более простым в использовании для новичков. Streamlit предлагает более продвинутые функции и возможности настройки, которые могут потребовать более крутой кривой обучения.

Интерактивность

  • Streamlit использует реактивную модель программирования, где любое изменение ввода запускает полный повторный запуск скрипта, немедленно обновляя все компоненты. Gradio по умолчанию обновляется только тогда, когда пользователь нажимает кнопку «Отправить», хотя его можно настроить для обновления в реальном времени.

Настройка

  • Gradio фокусируется на готовых компонентах для быстрой демонстрации моделей ИИ. Streamlit обеспечивает более широкие возможности настройки и гибкость для сложных проектов.

Развертывание

  • Развернув и Streamlit, и Gradio, я бы сказал, что проще развернуть приложение Streamlit, чем приложение Gradio. В Streamlit развертывание можно выполнить одним щелчком мыши через Streamlit Community Cloud. Эта функция встроена в любое приложение Streamlit, которое вы создаете. Gradio предлагает развертывание с использованием Hugging Face Spaces, но это требует больше работы. Однако ни один из методов не является особенно сложным.

Варианты использования

Streamlit отлично подходит для создания приложений, ориентированных на данные, и интерактивных панелей управления для сложных проектов. Gradio идеально подходит для быстрой демонстрации моделей машинного обучения и создания более простых приложений.

Код панели инструментов Gradio

Я разобью код на разделы и объясню каждый из них по мере продвижения.

Начнем с импорта необходимых внешних библиотек и загрузки полного набора данных из CSV-файла в Pandas DataFrame.

import gradio as gr import pandas as pd import matplotlib.pyplot as plt import datetime import warnings import os import tempfile from cachetools import cached, TTLCache warnings.filterwarnings(«ignore», category=FutureWarning, module=»seaborn») # —————————————————————— # 1) Загрузите данные CSV один раз # —————————————————————— csv_data = None def load_csv_data(): global csv_data # Необязательно: укажите типы столбцов, если они известны; при необходимости отрегулируйте dtype_dict = { «order_id»: «Int64», «customer_id»: «Int64», «product_id»: «Int64», «quantity»: «Int64», «price»: «float», «total»: «float», «customer_name»: «string», «product_names»: «string», «categories»: «string» } csv_data = pd.read_csv( «d:/sales_data/sales_data.csv», parse_dates=[«order_date»], dayfirst=True, # если даты в формате ДД/ММ/ГГГГ low_memory=False, dtype=dtype_dict ) load_csv_data()

Далее мы настраиваем кэш времени жизни с максимальным количеством элементов 128 и сроком действия 300 секунд. Это используется для хранения результатов дорогих вызовов функций и ускорения повторных поисков

Функция get_unique_categories возвращает список уникальных, очищенных (с заглавными буквами) категорий из DataFrame `csv_data`, кэшируя результат для более быстрого доступа.

Функция get_date_range возвращает минимальную и максимальную даты заказа из набора данных или None, если данные недоступны.

Функция filter_data фильтрует DataFrame csv_data на основе указанного диапазона дат и необязательной категории, возвращая отфильтрованный DataFrame.

Функция get_dashboard_stats извлекает сводные метрики — общий доход, общее количество заказов, среднюю стоимость заказа и верхнюю категорию — для заданных фильтров. Внутри она использует filter_data() для охвата набора данных, а затем вычисляет эти ключевые статистики.

Функция get_data_for_table возвращает подробный DataFrame отфильтрованных данных о продажах, отсортированных по order_id и order_date , включая дополнительный доход от каждой продажи.

Функция get_plot_data форматирует данные для построения графика путем суммирования доходов с течением времени, сгруппированных по дате.

Функция get_revenue_by_category агрегирует и возвращает доход по категориям, отсортированный по доходу, в указанном диапазоне дат и категории.

Функция get_top_products возвращает 10 лучших продуктов по доходу, отфильтрованных по диапазону дат и категории.

На основе аргумента orientation функция create_matplotlib_figure генерирует столбчатую диаграмму из данных и сохраняет ее как файл изображения, вертикальный или горизонтальный.

cache = TTLCache(maxsize=128, ttl=300) @cached(cache) def get_unique_categories(): глобальные csv_data если csv_data равен None: return [] cats = sorted(csv_data['categories'].dropna().unique().tolist()) cats = [cat.capitalize() для cat в cats] return cats def get_date_range(): глобальные csv_data если csv_data равен None или csv_data.empty: return None, None return csv_data['order_date'].min(), csv_data['order_date'].max() def filter_data(start_date, end_date, category): глобальные csv_data если isinstance(start_date, str): start_date = datetime.datetime.strptime(start_date, '%Y-%m-%d').date() если isinstance(end_date, str): end_date = datetime.datetime.strptime(end_date, '%Y-%m-%d').date() df = csv_data.loc[ (csv_data['order_date'] >= pd.to_datetime(start_date)) & (csv_data['order_date'] <= pd.to_datetime(end_date)) ].copy() если категория != "Все категории": df = df.loc[df['categories'].str.capitalize() == category].copy() вернуть df def get_dashboard_stats(start_date, end_date, category): df = filter_data(start_date, end_date, category) если df.empty: вернуть (0, 0, 0, "N/A") df['revenue'] = df['price'] * df['quantity'] total_revenue = df['revenue'].sum() total_orders = df['order_id'].nunique() avg_order_value = total_revenue / total_orders if total_orders else 0 cat_revenues = df.groupby('categories')['revenue'].sum().sort_values(ascending=False) top_category = cat_revenues.index[0] if not cat_revenues.empty else "N/A" return (total_revenue, total_orders, avg_order_value, top_category.capitalize()) def get_data_for_table(start_date, end_date, category): df = filter_data(start_date, end_date, category) if df.empty: return pd.DataFrame() df = df.sort_values(by=["order_id", "order_date"], ascending=[True, False]).copy() columns_order = [ "order_id", "order_date", "customer_id", "customer_name", "product_id", "product_names", "categories", "quantity", "price", "total" ] columns_order = [col for col in columns_order if col in df.columns] df = df[columns_order].copy() df['revenue'] = df['price'] * df['quantity'] return df def get_plot_data(start_date, end_date, category): df = filter_data(start_date, end_date, category) if df.empty: return pd.DataFrame() df['revenue'] = df['price'] * df['quantity'] plot_data = df.groupby(df['order_date'].dt.date)['revenue'].sum().reset_index() plot_data.rename(columns={'order_date': 'date'}, inplace=True) return plot_data def get_revenue_by_category(start_date, end_date, category): df = filter_data(start_date, end_date, category) if df.empty: return pd.DataFrame() df['revenue'] = df['price'] * df['quantity'] cat_data = df.groupby('categories')['revenue'].sum().reset_index() cat_data = cat_data.sort_values(by='revenue', ascending=False) return cat_data def get_top_products(start_date, end_date, category): df = filter_data(start_date, end_date, category) if df.empty: return pd.DataFrame() df['revenue'] = df['price'] * df['quantity'] prod_data = df.groupby('product_names')['revenue'].sum().reset_index() prod_data = prod_data.sort_values(by='revenue', ascending=False).head(10) return prod_data def create_matplotlib_figure(data, x_col, y_col, title, xlabel, ylabel, orientation='v'): plt.figure(figsize=(10, 6)) if data.empty: plt.text(0.5, 0.5, 'Нет доступных данных', ha='center', va='center') иначе: если ориентация == 'v': plt.bar(data[x_col], data[y_col]) plt.xticks(rotation=45, ha='right') иначе: plt.barh(data[x_col], data[y_col]) plt.gca().invert_yaxis() plt.title(title) plt.xlabel(xlabel) plt.ylabel(ylabel) plt.tight_layout() с tempfile.NamedTemporaryFile(delete=False, suffix=".png") как tmpfile: plt.savefig(tmpfile.name) plt.close() вернуть tmpfile.name

Функция update_dashboard извлекает ключевую статистику продаж (общий доход, общие заказы, средняя стоимость заказа и высшая категория) путем вызова функции get_dashboard_stats. Она собирает данные для трех различных визуализаций (доход с течением времени, доход по категориям и высшие продукты), затем использует create_matplotlib_figure для генерации графиков. Она подготавливает и возвращает таблицу данных (через функцию get_data_for_table()) вместе со всеми сгенерированными графиками и статистикой, чтобы их можно было отобразить на панели мониторинга.

Функция create_dashboard устанавливает границы дат (минимальные и максимальные даты) и устанавливает начальные значения фильтров по умолчанию. Она использует Gradio для создания пользовательского интерфейса (UI) с выбором дат, раскрывающимися списками категорий, отображениями ключевых метрик, вкладками графиков и таблицей данных. Затем она подключает фильтры так, чтобы изменение любого из них вызывало вызов функции update_dashboard , гарантируя, что визуальные элементы и метрики панели мониторинга всегда синхронизированы с выбранными фильтрами. Наконец, она возвращает собранный интерфейс Gradio, запущенный как веб-приложение.

def update_dashboard(start_date, end_date, category): total_revenue, total_orders, avg_order_value, top_category = get_dashboard_stats(start_date, end_date, category) # Генерация графиков income_data = get_plot_data(start_date, end_date, category) category_data = get_revenue_by_category(start_date, end_date, category) top_products_data = get_top_products(start_date, end_date, category) income_over_time_path = create_matplotlib_figure( income_data, 'date', 'revenue', «Revenue Over Time», «Date», «Revenue») income_by_category_path = create_matplotlib_figure( category_data, 'categories', 'revenue', «Revenue by Category», «Category», «Доход» ) top_products_path = create_matplotlib_figure( top_products_data, 'product_names', 'revenue', «Лучшие продукты», «Доход», «Название продукта», orientation='h' ) # Таблица данных table_data = get_data_for_table(start_date, end_date, category) return ( income_over_time_path, income_by_category_path, top_products_path, table_data, total_revenue, total_orders, avg_order_value, top_category ) def create_dashboard(): min_date, max_date = get_date_range() если min_date равно None или max_date равно None: min_date = datetime.datetime.now() max_date = datetime.datetime.now() default_start_date = min_date default_end_date = max_date with gr.Blocks(css=»»» footer {display: none !important;} .tabs {border: none !important;} .gr-plot {border: none !important; box-shadow: none !important;} «»») как панель мониторинга: gr.Markdown(«# Панель мониторинга эффективности продаж») # Фильтрует строку с помощью gr.Row(): start_date = gr.DateTime( label=»Дата начала», value=default_start_date.strftime('%Y-%m-%d'), include_time=False, type=»datetime» ) end_date = gr.DateTime( label=»Дата окончания», value=default_end_date.strftime('%Y-%m-%d'), include_time=False, type=»datetime» ) category_filter = gr.Dropdown( choices=[«Все категории»] + get_unique_categories(), label=»Категория», value=»Все категории» ) gr.Markdown(«# Key Metrics») # Строка статистики с gr.Row(): total_revenue = gr.Number(label=»Total Revenue», value=0) total_orders = gr.Number(label=»Total Orders», value=0) avg_order_value = gr.Number(label=»Average Order Value», value=0) top_category = gr.Textbox(label=»Top Category», value=»N/A») gr.Markdown(«# Visualisations») # Вкладки для графиков с gr.Tabs(): с gr.Tab(«Revenue Over Time»): income_over_time_image = gr.Image(label=»Revenue Over Time», container=False) с gr.Tab(«Revenue by Category»): income_by_category_image = gr.Image(label=»Revenue by Category», container=False) с gr.Tab(«Top Products»): top_products_image = gr.Image(label=»Top Products», container=False) gr.Markdown(«# Raw Data») # Таблица данных (под графиками) data_table = gr.DataFrame(label=»Sales Data», type=»pandas», interactive=False ) # При изменении фильтров обновляем все для f в [start_date, end_date, category_filter]: f.change( fn=lambda s, e, c: update_dashboard(s, e, c), inputs=[start_date, end_date, category_filter], outputs=[ income_over_time_image, income_by_category_image, top_products_image, data_table, total_revenue, total_orders, avg_order_value, top_category ] ) # Первоначальная загрузка dashboard.load( fn=lambda: update_dashboard(default_start_date, default_end_date, «All Категории»), outputs=[ изображение_дохода_за_время, изображение_дохода_по_категории, изображение_топ_продуктов, таблица_данных, общий_доход, общее_количество_заказов, среднее_значение_заказа, топ_категория] ) вернуть панель мониторинга, если __name__ == «__main__»: панель мониторинга = create_dashboard() панель мониторинга.launch(share=False)

Запуск программы

Создайте файл Python, например, gradio_test.py, и вставьте все вышеприведенные фрагменты кода. Сохраните его и запустите так,

(gradio_dashboard) $ python gradio_test.py * Запуск по локальному URL-адресу: http://127.0.0.1:7860 Чтобы создать публичную ссылку, установите `share=True` в `launch()`.

Щелкните по указанному локальному URL-адресу, и панель управления откроется в вашем браузере на весь экран.

Краткое содержание

В этой статье представлено подробное руководство по созданию интерактивной панели мониторинга эффективности продаж с использованием Gradio и CSV-файла в качестве исходных данных.

Gradio — это современный фреймворк с открытым исходным кодом на основе Python, который упрощает создание панелей мониторинга и приложений с графическим интерфейсом, управляемых данными. Разработанная мной панель мониторинга позволяет пользователям фильтровать данные по диапазонам дат и категориям продуктов, просматривать ключевые показатели, такие как общий доход и наиболее эффективные категории, изучать визуализации, такие как тенденции доходов и наиболее эффективные продукты, а также перемещаться по необработанным данным с помощью пагинации.

Я также упомянул некоторые ключевые различия между разработкой инструментов визуализации с использованием Gradio и Streamlit, еще одной популярной интерфейсной библиотеки Python.

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

Хотя я использовал CSV-файл для своих данных, изменение кода для использования другого источника данных, например, системы управления реляционными базами данных (СУРБД) типа SQLite, должно быть простым. Например, в моей другой статье из этой серии о создании аналогичной панели мониторинга с использованием Streamlit источником данных является база данных PostgreSQL.

Источник: towardsdatascience.com

❌ Нет тегов для этой статьи
Каталог бесплатных опенсорс-решений, которые можно развернуть локально и забыть о подписках

галерея

Фото сгенерированных лиц: исследование показывает, что люди не могут отличить настоящие лица от сгенерированных
Нейросети построили капитализм за трое суток: 100 агентов Claude заперли…
Скетч: цифровой осьминог и виртуальный мир внутри компьютера с человечком.
Сцена с жестами пальцами, где один жест символизирует "VPN", а другой "KHP".
‼️Paramount купила Warner Bros. Discovery — сумма сделки составила безумные…
Скриншот репозитория GitHub "Claude Scientific Skills" AI для научных исследований.
Структура эффективного запроса Claude с элементами задачи, контекста и референса.
Эскиз и готовая веб-страница платформы для AI-дизайна в современном темном режиме.
ideipro logotyp
Image Not Found
Звёздное небо с галактиками и туманностями, космос, Вселенная, астрофотография.

Система оповещения обсерватории Рубина отправила 800 000 сигналов в первую ночь наблюдений.

Астрономы будут получать оповещения о небесных явлениях в течение нескольких минут после их обнаружения. Теренс О'Брайен, редактор раздела «Выходные». Публикации этого автора будут добавляться в вашу ежедневную рассылку по электронной почте и в ленту новостей на главной…

Мар 2, 2026
Женщина с длинными тёмными волосами в синем свете, нейтральный фон.

Расследование в отношении 61-фунтовой машины, которая «пожирает» пластик и выплевывает кирпичи.

Обзор компактного пресса для мягкого пластика Clear Drop — и что будет дальше. Шон Холлистер, старший редактор Публикации этого автора будут добавляться в вашу ежедневную рассылку по электронной почте и в ленту новостей на главной странице вашего…

Мар 2, 2026
Черный углеродное волокно с текстурой плетения, отражающий свет.

Материал будущего: как работает «бессмертный» композит

Учёные из Университета штата Северная Каролина представили композит нового поколения, способный самостоятельно восстанавливаться после серьёзных повреждений.  Речь идёт о модифицированном армированном волокном полимере (FRP), который не просто сохраняет прочность при малом весе, но и способен «залечивать» внутренние…

Мар 2, 2026
Круглый экран с изображением замка и горы, рядом электронная плата.

Круглый дисплей Waveshare для креативных проектов

Круглый 7-дюймовый сенсорный дисплей от Waveshare создан для разработчиков и дизайнеров, которым нужен нестандартный экран.  Это IPS-панель с разрешением 1 080×1 080 пикселей, поддержкой 10-точечного ёмкостного сенсора, оптической склейкой и защитным закалённым стеклом, выполненная в круглом форм-факторе.…

Мар 2, 2026

Впишите свой почтовый адрес и мы будем присылать вам на почту самые свежие новости в числе самых первых