![](https://habrastorage.org/getpro/habr/upload_files/c2f/856/c92/c2f856c92b389711d0d21f6abdedeee8.png)
Несколько лет назад, занимался изучением теории музыки, продавал и писал аудио-инструментал для аренды или заказов. Изначально, процесс явно творческий, но вскоре, мой интерес к коммерческой части превысил и возник вопрос: «В каком же темпе создавать ритм музыки?».
Мною была замечена тенденция вариаций темпа популярных песен одного жанра, поэтому идея анализа крупной выборки лучших композиций, для определения популярного [часто: самого продаваемого] диапазона темпа исполнения, не покидала с тех пор…
BPM [в музыке] — показатель, для определения скорости исполнения композиции, путём измерения количества тактовых долей в минуту.
1: Пролог
Устанавливаем «Matplotlib» и «Pandas» с необходимыми зависимостями через pip-менеджер в консоли/терминале.
![«python -m pip install -V matplotlib» и «pip install pandas» «python -m pip install -V matplotlib» и «pip install pandas»](https://habrastorage.org/getpro/habr/upload_files/7b2/6e7/6fc/7b26e76fc68f4557e2b8310b6e4a71cc.jpg)
Создаём директорию, а потом виртуальное окружение для проекта. После, подключаем библиотеки в IDE [в моём случае: PyCharm].
![File — Settings — Project: [...] — Python Interpreter File — Settings — Project: [...] — Python Interpreter](https://habrastorage.org/getpro/habr/upload_files/590/20a/990/59020a990cba62c14e17a86425e14cc4.gif)
2: BPM
BPM будем вычислять через функцию «Detect tempo» в FL Studio и через сайт tunebat.com
![ПКМ по верхней левой иконке на звуковой дорожке — Detect tempo — Выбрать диапазон ПКМ по верхней левой иконке на звуковой дорожке — Detect tempo — Выбрать диапазон](https://habrastorage.org/getpro/habr/upload_files/7d1/137/25e/7d113725ebae86f2b37c65929759d455.gif)
3: DataSet
Начинаем создание DataSet’а [выборки-коллекции данных] в Excel, для каждого жанра. Экспортируем в CSV-формат с настройками разделителя — запятой. Следующие CSV-файлы создавал в IDE, так удобнее. Выборки перемещаем в директорию, где находится файл самой программы.
В первой строке CSV-файлов указываются параметры, которые разделяются запятыми. Следующие строки содержат уже значения этих параметров. При окончательной проверке, DataSet должен последовательно содержать данные: названия трека, BPM и год выхода композиции. Будем использовать информацию выборки в сто песен, для каждого жанра из выбранных пяти.
![Параметры: «name» — название трека; «bpm» — темп; «year» — год релиза Параметры: «name» — название трека; «bpm» — темп; «year» — год релиза](https://habrastorage.org/getpro/habr/upload_files/f8b/9ac/21c/f8b9ac21c5e04e1d3825f8deffd91da4.gif)
4: Rap — построение точечной диаграммы и гистограммы
Выборка взята здесь: rollingstone.com/100-greatest-hip-hop-songs-of-all-time
Сам CSV-DataSet: github.com/Rap.csv
На основе информации DataSet'а, создаём точечную диаграмму [Scatter Plots] для изучения взаимосвязи между BPM и годом выпуска, а также для отображения концентраций при ранжировании данных.
![Видно, что с 1980 по 2005 гг. основным темпом был диапазон в 90-105 BPM Видно, что с 1980 по 2005 гг. основным темпом был диапазон в 90-105 BPM](https://habrastorage.org/getpro/habr/upload_files/1c0/476/a51/1c0476a51b9d524df569b76f58b4656e.png)
«Код точечной диаграммы с комментариями»
from matplotlib import pyplot as plt # Первый каноничный импорт
import pandas as pd # Второй каноничный импорт для обработки DataSet'а
plt.style.use('fivethirtyeight') # Назначаем стилистику визуализации
data_set = pd.read_csv('Rap.csv') # Считываем данные SCV-файла с DataSet'ом
bpm = data_set['bpm'] # Переменная, для параметра BPM в каждой строке
year = data_set['year'] # Переменная, для параметра "год релиза" в каждой строке
plt.scatter( # Построение точечного графика и его настройка
bpm, year, # Данные для осей «x» и «y»
c=bpm, # Привязка цвета к нужной оси
s=bpm*1.5, # Зависимость размера точки
cmap='gist_heat', # Цветовая карта графика
edgecolor='black', # Цвет контура точки
linewidth=.7 # Толщина контура точки
)
bar = plt.colorbar( # Построение шкалы BPM
orientation='horizontal', # Ориентация шкалы
shrink=0.8, # Масштаб шкалы
extend='both', # Скос краёв шкалы
extendfrac=.1 # Угол скоса краёв
)
bar.set_label('Шкала ударов в минуту', fontsize=18) # Подпись шкалы
plt.title('Популярность скорости ' # Заголовок графика
'исполнения в Rap\'е ', fontsize=25)
plt.xlabel('BPM', fontsize=18) # Ось абсцисс
plt.ylabel('Год релиза', fontsize=18) # Ось ординат
plt.tight_layout() # Настройка параметров подзаголовков в области отображения
plt.show() # Вывод на экран
Если диаграмма отражает точечное положение трека в зависимости двух переменных, — BPM и года релиза, — то гистограмма покажет частоту-количество попаданий значения BPM для каждого диапазона на шкале. Таким образом, определится популярность определенного темпа.
![Самый популярный диапазон: 80-100 BPM Самый популярный диапазон: 80-100 BPM](https://habrastorage.org/getpro/habr/upload_files/cad/5f0/98a/cad5f098a63c6fded55a04f1ec8191dd.png)
«Код гистограммы без комментариев»
import pandas as pd
from matplotlib import pyplot as plt
from collections import Counter
plt.style.use("fivethirtyeight")
data_set = pd.read_csv('Rap end.csv')
index = data_set['number']
ranges = data_set['bpm_range']
counter = Counter()
for index in ranges:
counter.update(index.split(';'))
range_bpm = []
value = []
for item in counter.most_common(100):
range_bpm.append(item[0])
value.append(item[1])
range_bpm.reverse()
value.reverse()
plt.barh(
range_bpm, value,
linewidth=.5,
edgecolor='black',
color='#e85b45',
label='Количество точек на предыдущем графике'
)
plt.legend()
plt.title('Популярность интервала значений BPM в rap\'е', fontsize=25)
plt.xlabel('Количество песен в диапазоне BPM', fontsize=18)
plt.ylabel('Диапазоны BPM', fontsize=18)
plt.tight_layout()
plt.show()
5: Рок
Выборка взята здесь: rockfm.ru/top100
Сам CSV-DataSet: github.com/Rock.csv
Однозначности пока что нет, — особенность жанра. — поэтому, второй график построен при округлении параметра «year/год выхода композиции».
![](https://habrastorage.org/getpro/habr/upload_files/9f5/ce9/517/9f5ce951735c1252156cd31b31f7b081.png)
«Код точечной диаграммы с комментариями»
from matplotlib import pyplot as plt # Первый каноничный импорт
import pandas as pd # Второй каноничный импорт для обработки DataSet'а
plt.style.use('fivethirtyeight') # Назначаем стилистику визуализации
data_set = pd.read_csv('Rock.csv') # Считываем данные SCV-файла с DataSet'ом
bpm = data_set['bpm'] # Переменная, для параметра BPM в каждой строке
year = data_set['year'] # Переменная, для параметра "год релиза" в каждой строке
plt.scatter( # Построение точечного графика и его настройка
bpm, year, # Данные для осей «x» и «y»
c=bpm, # Привязка цвета к нужной оси
s=bpm*1.5, # Зависимость размера точки
cmap='gist_heat', # Цветовая карта графика
edgecolor='black', # Цвет контура точки
linewidth=.7 # Толщина контура точки
alpha=.7 # Прозрачность точки
)
bar = plt.colorbar( # Построение шкалы BPM
orientation='horizontal', # Ориентация шкалы
shrink=0.8, # Масштаб шкалы
extend='both', # Скос краёв шкалы
extendfrac=.1 # Угол скоса краёв
)
bar.set_label('Шкала ударов в минуту', fontsize=18) # Подпись шкалы
plt.title('Популярность скорости ' # Заголовок графика
'исполнения в роке', fontsize=25)
plt.xlabel('BPM', fontsize=18) # Ось абсцисс
plt.ylabel('Год релиза', fontsize=18) # Ось ординат
plt.tight_layout() # Настройка параметров подзаголовков в области отображения
plt.show() # Вывод на экран
![Самые популярные диапазоны: 120-140 и 100-120 BPM Самые популярные диапазоны: 120-140 и 100-120 BPM](https://habrastorage.org/getpro/habr/upload_files/666/f6d/c1a/666f6dc1a69f2ea1afcb8a7554ecf458.png)
«Код гистограммы без комментариев»
import pandas as pd
from matplotlib import pyplot as plt
from collections import Counter
plt.style.use("fivethirtyeight")
data_set = pd.read_csv('Rock end.csv')
index = data_set['number']
ranges = data_set['bpm_range']
counter = Counter()
for index in ranges:
counter.update(index.split(';'))
range_bpm = []
value = []
for item in counter.most_common(100):
range_bpm.append(item[0])
value.append(item[1])
range_bpm.reverse()
value.reverse()
plt.barh(
range_bpm, value,
linewidth=.5,
edgecolor='black',
color='#e85b45',
label='Количество точек на предыдущем графике'
)
plt.legend()
plt.title('Популярность интервала значений BPM в роке', fontsize=25)
plt.xlabel('Количество песен в диапазоне BPM', fontsize=18)
plt.ylabel('Диапазоны BPM', fontsize=18)
plt.tight_layout()
plt.show()
6: Блюз
Выборка взята здесь: digitaldreamdoor.com/best_bluesong
Сам CSV-DataSet: github.com/Blues.csv
![Видно высокую концентрацию использования темпа около 100 BPM в 90-х Видно высокую концентрацию использования темпа около 100 BPM в 90-х](https://habrastorage.org/getpro/habr/upload_files/cea/40b/515/cea40b51530303cd9c6b53120919d1e1.png)
«Код точечной диаграммы с комментариями»
from matplotlib import pyplot as plt # Первый каноничный импорт
import pandas as pd # Второй каноничный импорт для обработки DataSet'а
plt.style.use('fivethirtyeight') # Назначаем стилистику визуализации
data_set = pd.read_csv('Blues.csv') # Считываем данные SCV-файла с DataSet'ом
bpm = data_set['bpm'] # Переменная, для параметра BPM в каждой строке
year = data_set['year'] # Переменная, для параметра "год релиза" в каждой строке
plt.scatter( # Построение точечного графика и его настройка
bpm, year, # Данные для осей «x» и «y»
c=bpm, # Привязка цвета к нужной оси
s=bpm*1.5, # Зависимость размера точки
cmap='gist_heat', # Цветовая карта графика
edgecolor='black', # Цвет контура точки
linewidth=.7 # Толщина контура точки
)
bar = plt.colorbar( # Построение шкалы BPM
orientation='horizontal', # Ориентация шкалы
shrink=0.8, # Масштаб шкалы
extend='both', # Скос краёв шкалы
extendfrac=.1 # Угол скоса краёв
)
bar.set_label('Шкала ударов в минуту', fontsize=18) # Подпись шкалы
plt.title('Популярность скорости ' # Заголовок графика
'исполнения в блюзе', fontsize=25)
plt.xlabel('BPM', fontsize=18) # Ось абсцисс
plt.ylabel('Год релиза', fontsize=18) # Ось ординат
plt.tight_layout() # Настройка параметров подзаголовков в области отображения
plt.show() # Вывод на экран
![Самый популярный диапазон: 100-120 BPM Самый популярный диапазон: 100-120 BPM](https://habrastorage.org/getpro/habr/upload_files/73f/ef6/8d7/73fef68d727cb00c55dfaf351cba328a.png)
«Код гистограммы без комментариев»
import pandas as pd
from matplotlib import pyplot as plt
from collections import Counter
plt.style.use("fivethirtyeight")
data_set = pd.read_csv('Blues end.csv')
index = data_set['number']
ranges = data_set['bpm_range']
counter = Counter()
for index in ranges:
counter.update(index.split(';'))
range_bpm = []
value = []
for item in counter.most_common(100):
range_bpm.append(item[0])
value.append(item[1])
range_bpm.reverse()
value.reverse()
plt.barh(
range_bpm, value,
linewidth=.5,
edgecolor='black',
color='#e85b45',
label='Количество точек на предыдущем графике'
)
plt.legend()
plt.title('Популярность интервала значений BPM в блюзе', fontsize=25)
plt.xlabel('Количество песен в диапазоне BPM', fontsize=18)
plt.ylabel('Диапазоны BPM', fontsize=18)
plt.tight_layout()
plt.show()
7: Chillout
Выборка взята здесь: open.spotify.com
Сам CSV-DataSet: github.com/Chillout.csv
Много наложений точек друг на друга. К сожалению, не знаю, как это исправить. Пришлось сделать точки более прозрачными, с помощью аргумента «alpha» функции «.scatter».
![](https://habrastorage.org/getpro/habr/upload_files/37a/45f/448/37a45f448688d6af5cd9ab93f54a8589.png)
«Код точечной диаграммы с комментариями»
from matplotlib import pyplot as plt # Первый каноничный импорт
import pandas as pd # Второй каноничный импорт для обработки DataSet'а
plt.style.use('fivethirtyeight') # Назначаем стилистику визуализации
data_set = pd.read_csv('Chillout.csv') # Считываем данные SCV-файла с DataSet'ом
bpm = data_set['bpm'] # Переменная, для параметра BPM в каждой строке
year = data_set['year'] # Переменная, для параметра "год релиза" в каждой строке
plt.scatter( # Построение точечного графика и его настройка
bpm, year, # Данные для осей «x» и «y»
c=bpm, # Привязка цвета к нужной оси
s=bpm*1.5, # Зависимость размера точки
cmap='gist_heat', # Цветовая карта графика
edgecolor='black', # Цвет контура точки
linewidth=.7 # Толщина контура точки
alpha=.5 # Прозрачность точки
)
bar = plt.colorbar( # Построение шкалы BPM
orientation='horizontal', # Ориентация шкалы
shrink=0.8, # Масштаб шкалы
extend='both', # Скос краёв шкалы
extendfrac=.1 # Угол скоса краёв
)
bar.set_label('Шкала ударов в минуту', fontsize=18) # Подпись шкалы
plt.title('Популярность скорости ' # Заголовок графика
'исполнения в Chillout', fontsize=25)
plt.xlabel('BPM', fontsize=18) # Ось абсцисс
plt.ylabel('Год релиза', fontsize=18) # Ось ординат
plt.tight_layout() # Настройка параметров подзаголовков в области отображения
plt.show() # Вывод на экран
![Самый популярный диапазон: 80-100 Самый популярный диапазон: 80-100](https://habrastorage.org/getpro/habr/upload_files/378/192/7d4/3781927d40aae6fbb00949e8f4de4466.png)
«Код гистограммы без комментариев»
import pandas as pd
from matplotlib import pyplot as plt
from collections import Counter
plt.style.use("fivethirtyeight")
data_set = pd.read_csv('Chillout end.csv')
index = data_set['number']
ranges = data_set['bpm_range']
counter = Counter()
for index in ranges:
counter.update(index.split(';'))
range_bpm = []
value = []
for item in counter.most_common(100):
range_bpm.append(item[0])
value.append(item[1])
range_bpm.reverse()
value.reverse()
plt.barh(
range_bpm, value,
linewidth=.5,
edgecolor='black',
color='#e85b45',
label='Количество точек на предыдущем графике'
)
plt.legend()
plt.title('Популярность интервала значений BPM в Chillout', fontsize=25)
plt.xlabel('Количество песен в диапазоне BPM', fontsize=18)
plt.ylabel('Диапазоны BPM', fontsize=18)
plt.tight_layout()
plt.show()
8: EDM
Выборка взята здесь: edmcharts.net
Сам CSV-DataSet: github.com/EDM.csv
Здесь также для наглядности пришлось сделать точки ещё более прозрачными. Если кто-то знает, как исправить дефект наложения, прошу написать в комментариях.
![Довольно однозначно вышло... Довольно однозначно вышло...](https://habrastorage.org/getpro/habr/upload_files/d93/642/e68/d93642e6834a20bc4df72c5e66366a79.png)
«Код точечной диаграммы с комментариями»
from matplotlib import pyplot as plt # Первый каноничный импорт
import pandas as pd # Второй каноничный импорт для обработки DataSet'а
plt.style.use('fivethirtyeight') # Назначаем стилистику визуализации
data_set = pd.read_csv('EDM.csv') # Считываем данные SCV-файла с DataSet'ом
bpm = data_set['bpm'] # Переменная, для параметра BPM в каждой строке
year = data_set['year'] # Переменная, для параметра "год релиза" в каждой строке
plt.scatter( # Построение точечного графика и его настройка
bpm, year, # Данные для осей «x» и «y»
c=bpm, # Привязка цвета к нужной оси
s=bpm*1.5, # Зависимость размера точки
cmap='gist_heat', # Цветовая карта графика
edgecolor='black', # Цвет контура точки
linewidth=.7 # Толщина контура точки
alpha=.2 # Прозрачность точки
)
bar = plt.colorbar( # Построение шкалы BPM
orientation='horizontal', # Ориентация шкалы
shrink=0.8, # Масштаб шкалы
extend='both', # Скос краёв шкалы
extendfrac=.1 # Угол скоса краёв
)
bar.set_label('Шкала ударов в минуту', fontsize=18) # Подпись шкалы
plt.title('Популярность скорости ' # Заголовок графика
'исполнения в EDM', fontsize=25)
plt.xlabel('BPM', fontsize=18) # Ось абсцисс
plt.ylabel('Год релиза', fontsize=18) # Ось ординат
plt.tight_layout() # Настройка параметров подзаголовков в области отображения
plt.show() # Вывод на экран
![Самый популярный диапазон: 120-140 Самый популярный диапазон: 120-140](https://habrastorage.org/getpro/habr/upload_files/f09/23b/174/f0923b174059c222e961d5f72dddee2b.png)
«Код гистограммы без комментариев»
import pandas as pd
from matplotlib import pyplot as plt
from collections import Counter
plt.style.use("fivethirtyeight")
data_set = pd.read_csv('EDM end.csv')
index = data_set['number']
ranges = data_set['bpm_range']
counter = Counter()
for index in ranges:
counter.update(index.split(';'))
range_bpm = []
value = []
for item in counter.most_common(100):
range_bpm.append(item[0])
value.append(item[1])
range_bpm.reverse()
value.reverse()
plt.barh(
range_bpm, value,
linewidth=.5,
edgecolor='black',
color='#e85b45',
label='Количество точек на предыдущем графике'
)
plt.legend()
plt.title('Популярность интервала значений BPM в EDM', fontsize=25)
plt.xlabel('Количество песен в диапазоне BPM', fontsize=18)
plt.ylabel('Диапазоны BPM', fontsize=18)
plt.tight_layout()
plt.show()
9: Заключение
Самым простым графиком сравним количество попаданий в каждый диапазон, композиций, из всех проанализированных ранее жанров*.
* такие жанры как ethnic, ambient, folk, dubstep, reggae и др, не удалось к сожалению разобрать из-за отсутствия качественной выборки...
![](https://habrastorage.org/getpro/habr/upload_files/396/bd1/87e/396bd187ec9439b3cef2ba88806028d3.gif)
![](https://habrastorage.org/getpro/habr/upload_files/39c/4d4/ddd/39c4d4ddde9305c7c1f3f3dbc070f3f8.png)
BPM/Кол-во треков | <60 | 60-80 | 80-100 | 100-120 | 120-140 | 140-160 | 160-180 |
Blues | 2 | 9 | 25 | 35 | 15 | 6 | 8 |
Chillout | 11 | 35 | 18 | 19 | 12 | 5 | |
EDM | 1 | 3 | 21 | 67 | 6 | 2 | |
Rap | 5 | 61 | 20 | 7 | 4 | 3 | |
Rock | 6 | 20 | 25 | 27 | 11 | 11 | |
Итог: | 2 | 32 | 144 | 119 | 135 | 39 | 29 |
«Простой код, простого графика»
from matplotlib import pyplot as plt
plt.style.use('fivethirtyeight')
x = ['<60', '60-80', '80-100', '100-120', '120-140', '140-160', '160-180']
y = [2, 32, 144, 119, 135, 39, 29]
plt.plot(x, y, label='BPM', c='#e85b45')
plt.legend()
plt.title('Сравнение всех диапазонов BPM во всех жанрах', fontsize=25)
plt.xlabel('Диапазон BPM', fontsize=18)
plt.ylabel('Количество треков', fontsize=18)
plt.tight_layout()
plt.show()
Sultansoy
Автор, а я правильно вас понял, что вы для 500 треков проклацали кнопки, чтобы получить бпм в фруктах?
SCUIIIPTOR Автор
Нет, это было бы невероятно долго и не разумно))
Функционал Fruity Loops использовался для тех композиций, данных о BPM которых, не было на сайте указанном в главе «BPM».