«Это 26-й день моего участия в ноябрьском испытании обновлений. Подробную информацию об этом событии см.:Вызов последнего обновления 2021 г."
Набор данных в этой статье взят из набора данных «Черная пятница» на веб-сайте Kaggle. Фон набора данных основан на Черной пятнице. Черная пятница — это крупная покупка в западных странах. Подобно событию «Double Eleven» в моей стране, торговые центры откроются в Черную пятницу. Множество предложений и скидок на последнюю большую распродажу перед Рождеством, чтобы получить максимальную отдачу от затраченных средств в конце года. Чтобы гарантировать, что права на конфиденциальность операционных компаний и пользователей-потребителей, которые предоставляют набор данных, не нарушаются, веб-сайт выполнил «обработку десенсибилизации» для некоторых функций в наборе данных. Розничная компания с ограниченной ответственностью хочет понять покупательское поведение клиентов (особенно сумму покупки) для различных продуктов в разных категориях. Предоставляет информацию о покупках для клиентской базы избранных продуктов большого объема в Черную пятницу. Набор данных содержит две части информации о демографии клиентов (возраст, пол, семейное положение, категория города, длина поселения) и детали товара (идентификатор товара и категория товара) и общую сумму покупки. набор данных kaggle:Woohoo.Карта переформирована.com/Я получил заказ/Первоначально…
Конкретное объяснение каждого поля показано в Таблице 11:
Таблица 1-1 Таблица пояснений к полям набора данных
поле | значение |
---|---|
User_ID | Код пользователя |
Product_ID | Код товара |
Gender | Пол (M для мужчин, F для женщин) |
Age | Возраст (0-17, 18-25, 26-35, 36-45, 46-50, 51-55, 55+, 7 типов) |
Occupation | Профессия (используйте числа для обозначения конкретных профессий, всего 20 профессий) |
City_Category | Классификация городов (разделена на три категории городов: ABC) |
Stay_in_Current_City_Years | Годы проживания в текущем городе (0, 1, 2, 3, 4+, 5 типа) |
Marital_Status | Семейное положение (0 не замужем, 1 женат) |
Product_Category_1 | Классификация товара 1 (одежда, 20 видов, представлена 1-20) |
Product_Category_2 | Категория продукта 2 (электроника) |
Product_Category_3 | Категория продукта 3 (предметы мебели) |
Purchase | Сумма покупки (в долларах США) |
# 导入数据
df = pd.read_csv("product_data.csv")
df.head()
Фундаментальный анализ
информация для основной информации
Используйте информацию, чтобы просто понять информацию о данных
df.info()
Что позволяет нам увидеть функция info()?
1. Тип данных Dtype
Можно обнаружить, что User_ID — это int, а Product_ID — тип объекта, потому что Product_ID содержит буквы, а значит, содержит только букву P? Или есть что-то еще? Нам нужно проверить и проанализировать это позже.
Пол/Возраст/City_Category/Stay_In_Current_City_YearsЭти функции также являются объектными типами, поскольку содержат строки. Серьезной проблемы нет. Мы продолжим структурированную обработку.
Occupation/Marital_Status — это чисто числовые переменные, и уместно использовать int для категориальных переменных.
Product_Category_1/Product_Category_2/Product_Category_3 Интересно, что хотя все они являются продуктами, номер 1 — int, а остальные — числа с плавающей запятой. Однако категориальные переменные не могут быть числами с плавающей запятой.После просмотра данных решите, нужно ли преобразовывать тип данных.
Подводя итог, можно сказать, что типы данных всех данных хаотичны, существует большое количество неструктурированных строковых данных, которые необходимо преобразовать в соответствующие числовые данные, а некоторые данные необходимо преобразовать в типы данных.
2. Отсутствуют ненулевые данные\
Интуитивно можно обнаружить, что Product_Category_2/Product_Category_3 отсутствует, а отсутствие Product_Category_3 кажется довольно серьезным.
С таким большим объемом данных удаление определенно невозможно, поэтому нам нужно подумать о некоторых эффективных стратегиях заполнения, чтобы справиться с этими пропущенными значениями.
import missingno
df.isna().sum()/df.shape[0]
# 条形图 看缺失程度
missingno.bar(df)
# 矩阵图 看缺失分布
missingno.matrix(df)
Подытожим, что мы знаем:
Содержит три типа данных: int64, object и float64.
Всего 537577 записей транзакций, 12 полей
Поле Product_Category_2 имеет 31% отсутствующих значений, а Product_Category_3 имеет 69% отсутствующих значений.
Информация о месторождении полезных ископаемых
# 查看消费用户数目和物品数目
print('消费者人数:',df.User_ID.nunique())
print('商品种类:',df.Product_ID.nunique())
# 总消费金额
print('总消费金额 {}'.format(df.Purchase.sum()),"美元")
# 让我看看是谁那么买 选出消费用户TOP10
user_Purchase_top10 = df.groupby('User_ID').Purchase.count().reset_index(name='下单次数')
user_Purchase_top10['总消费额'] = df.groupby('User_ID').Purchase.sum().values
user_Purchase_top10.sort_values('下单次数',ascending=False).head(10)
Количество потребителей: 5891
Тип товара: 3623
«Славные парни» потратили 5 миллиардов долларов!
# 查看商品类别2有多少不同的商品
print(df.Product_Category_2.unique())
print(df.Product_Category_3.unique())
[nan, 6., 14., 2., 8., 15., 16., 11., 5., 3., 4., 12., 9.,10., 17., 13., 7., 18.]
[nan, 14., 17., 5., 4., 16., 15., 8., 9., 13., 6., 12., 3.,18., 11., 10.]
Product_Category_2 и Product_Category_3 — положительные целые числа от 2 до 18, Для nan можно использовать медианное заполнение. Однако также можно предположить, что элемент с отсутствующим значением не принадлежит к этим двум категориям элементов, поэтому отсутствующее значение заменяется на 0 для создания новой категории.
# 为了保证原始数据的不动copy一份源数据
# 并且希望得到一张新的表 记录5819位消费者的信息
UserInfo = df.copy()
UserInfo = UserInfo.pivot_table(index = ['User_ID','Gender','Age','Occupation','City_Category','Stay_In_Current_City_Years',\
'Marital_Status'],values = ['Purchase'],aggfunc = 'sum').reset_index()
UserInfo.nunique()
Потребительские характеристики: Пол - 2 вида
Возрастная группа - 7 видов
Род занятий - 21 вид
Города - 3
Годы проживания - 5 типов
Семейное положение - 2 вида\
визуализация данных
Создайте функцию feature_group (данные, группа, текст), классифицируйте по потребительским характеристикам и выведите многослойную круговую диаграмму.
colors = ['salmon','lightskyblue','#FFF68F','palegreen','lightpink','silver','burlywood','plum','rosybrown']
def feature_group(data,group,text): #data:数据集,group:要分类的字段
data['Number'] = 1
feature_class = data.groupby(group)[['Purchase','Number']].sum().sort_values('Purchase',ascending = False)
#内圈为消费者人数占比
plt.pie(x = feature_class.Number,colors = colors,radius = 1.2,
wedgeprops = {'width':1,'edgecolor':'w'},autopct = '%.f%%',pctdistance = 0.7)
#外圈为消费金额占比
plt.pie(x = feature_class.Purchase,colors = colors,radius = 1.8,
wedgeprops = {'width':0.6,'edgecolor':'w'},autopct = '%.f%%',pctdistance = 0.85)
# 图例
plt.legend(feature_class.index,bbox_to_anchor = (1.2,1.2),fontsize = 15)
# 图表名
plt.title('不同'+text+'对应消费人数和消费金额占比图',y = 1.25,fontsize = 15)
plt.show()
Пол
feature_group(UserInfo,'Gender','性别')
malesPurchaserData = df.loc[df['Gender'] == 'M']
malesPurchaseMean = np.mean(malesPurchaserData['Purchase'])
print("男性消费用户人均销售额 = ",malesPurchaseMean)
femalsPurchaserData = df.loc[df['Gender'] == 'F']
femalsPurchaseMean = np.mean(femalsPurchaserData['Purchase'])
print("女性消费用户人均销售额 = ",femalsPurchaseMean)
Продажи на одного потребителя-мужчину = 9504,771712960679.
Продажи на женщину-потребителя = 8809,761348593387
Потребители-мужчины составляют 72%, а объем потребления составляет 77%, что намного выше, чем у женщин.Средний объем потребления мужчин также немного выше, чем у женщин.
возраст
feature_group(UserInfo,'Age','年龄')
Количество потребителей в возрасте 26-35 лет составило 35%, объем потребления составил 40%, а средний объем потребления также был выше, чем в других возрастных группах.
Количество потребителей в возрасте 36-45 лет составило 20%, а объем потребления - 20%, а количество потребителей в возрасте 18-25 лет - 18%, а объем потребления - 18%.
Молодежь и люди среднего возраста в возрасте от 18 до 45 лет составили 73% потребителей, а объем потребления составил 78%, они и были основными потребителями данного мероприятия.
Профессия
# 职业太多了重新定义个大一点图函数
def feature_group_mul(data,group,text): #data:数据集,group:要分类的字段
data['Number'] = 1
feature_class = data.groupby(group)[['Purchase','Number']].sum().sort_values('Purchase',ascending = False)
#内圈为消费者人数占比
plt.figure(figsize=(10,8))
plt.pie(x = feature_class.Number,colors = colors,radius = 1.2,
wedgeprops = {'width':1,'edgecolor':'w'},autopct = '%.f%%',pctdistance = 0.7)
#外圈为消费金额占比
plt.pie(x = feature_class.Purchase,colors = colors,radius = 1.8,
wedgeprops = {'width':0.6,'edgecolor':'w'},autopct = '%.f%%',pctdistance = 0.85)
# 图例
plt.legend(feature_class.index,bbox_to_anchor = (1.5,1.2),fontsize = 15)
# 图表名
plt.title('不同'+text+'对应消费人数和消费金额占比图',y = 1.3,fontsize = 15)
feature_group_mul(UserInfo,'Occupation','职业')
Профессии с наибольшей долей потребителей - 4, 0 и 7, что составляет 13%, 12% и 11% соответственно.
Профессии с наибольшим объемом потребления также равны 4, 0 и 7, что составляет 13%, 12% и 11% соответственно.
feature_group(UserInfo,'City_Category','城市')
Город с наибольшей долей потребителей — это город C (53%), но объем потребления в городе C составляет всего 33%.
Городом с наибольшей долей потребления является город Б, который составляет 42%, а количество потребителей в городе Б составляет 29%.
Средний объем потребления в городах A и B относительно высок, а средний объем потребления в городе C намного ниже, чем в городах A и B.
feature_group(UserInfo,'Stay_In_Current_City_Years','居住年数')
Количество потребителей, проживших один год, было самым большим, и сумма потребления также была самой большой.
feature_group(UserInfo,'Marital_Status','婚姻状况')
Количество потребления, объем потребления и средний объем потребления у неженатых людей выше, чем у женатых.
#针对城市、年龄两个特征进行进一步探索
fig = plt.figure(figsize=(10,5))
width_bar = 0.12
width_add = 0
for c,Age in enumerate(sorted(UserInfo.Age.unique())):
City_Age = UserInfo[UserInfo.Age == Age].groupby('City_Category').Purchase.sum()\
.reset_index(name = 'Purchase')
City_Age['Purchase'] = round(City_Age['Purchase'] / 1000000,1)
plt.bar(np.arange(UserInfo.City_Category.nunique()) + width_add,City_Age['Purchase'],width = width_bar,\
color = colors[c],label = Age)
for x,y in enumerate(City_Age.Purchase):
plt.text(x + width_add,y + 8,y,ha = 'center')
width_add += width_bar
plt.title('不同城市、年龄消费金额对比图',y = 1.02,fontsize = 13)
plt.xlabel('城市',fontsize = 12)
plt.ylabel('消费金额(百万美元)',fontsize = 12)
plt.xlim(-0.1,3.2)
plt.ylim(0,900)
plt.xticks(np.arange(UserInfo.City_Category.nunique()) + 0.3,sorted(UserInfo.City_Category.unique()))
plt.tight_layout()
plt.legend()
plt.show()
Молодые люди в возрасте 26-35 лет являются основным потребителем, и объем потребления выше, чем у других возрастных групп.
Объем потребления, вносимый потребителями молодого и среднего возраста в возрасте от 18 до 45 лет, чрезвычайно высок в городах А и В, но ниже в городе С.
Несовершеннолетние потребители в возрасте от 1 до 17 лет и пожилые потребители в возрасте 55+ лет в городе C вносят больший вклад, чем потребители в городах A и B.
Предварительное предположение, что город C является городом оттока населения.
#针对城市、婚姻状态两个特征进行进一步探索
fig = plt.figure(figsize=(10,5))
width_bar = 0.12
width_add = 0
for c,M in enumerate(sorted(UserInfo.Marital_Status.unique())):
City_M = UserInfo[UserInfo.Marital_Status == M].groupby('City_Category').Purchase.sum()\
.reset_index(name = 'Purchase')
City_M['Purchase'] = round(City_M['Purchase'] / 1000000,1)
plt.bar(np.arange(UserInfo.City_Category.nunique()) + width_add,City_M['Purchase'],width = width_bar,\
color = colors[c],label = M)
for x,y in enumerate(City_M.Purchase):
plt.text(x + width_add,y + 8,y,ha = 'center')
width_add += width_bar
plt.title('不同城市、婚姻状态消费金额对比图',y = 1.02,fontsize = 13)
plt.xlabel('城市',fontsize = 12)
plt.ylabel('消费金额(百万美元)',fontsize = 12)
plt.xlim(-0.1,3.2)
plt.ylim(0,1500)
plt.xticks(np.arange(UserInfo.City_Category.nunique()) + 0.1,sorted(UserInfo.City_Category.unique()))
plt.tight_layout()
plt.legend()
plt.show()
#先来看一看销售额排名前20的商品
Product_Top20 = df.groupby('Product_ID').Purchase.sum().reset_index(name = 'Purchase')
Product_Top20 = Product_Top20.sort_values('Purchase',ascending = False)[:20]
Product_Top20['Purchase'] = round(Product_Top20['Purchase'] / 1000000,1)
fig = plt.figure(figsize=(10,4.5))
plt.bar(range(20),Product_Top20.Purchase,color = colors,width = 0.6)
for x,y in enumerate(Product_Top20.Purchase):
plt.text(x,y + 0.5,y,ha = 'center')
plt.xticks(range(20),Product_Top20.Product_ID,rotation = -90)
plt.ylim(0,30)
plt.xlabel('产品品类',fontsize = 12)
plt.ylabel('销售额(百万美元)')
plt.title('Top20商品销售额对比图')
plt.tight_layout()
plt.show()
Продажи товаров по 16 категориям превысили 20 миллионов долларов США, самая высокая - P00025442, 27,5 миллионов долларов США.
#看一看销售额前20%的商品占总销售额的比例
Product_Group = df.groupby('Product_ID').Purchase.sum().sort_values(ascending = False)
Product_Group[:int(df.Product_ID.nunique() * 0.2)].sum() / Product_Group.sum()
0.7317218081007266
На первые 20% продаж приходилось 73% продаж, в основном в соответствии с правилом 28.
#因为Product_Category_2、Product_Category_3缺失值太多,暂不分析,只对Product_Category_1(类别1)进行分析
#分析一下类别1各个类别的销售额
Category_Group = round(df.groupby('Product_Category_1').Purchase.sum().sort_values(ascending = False) /10000000,1)
fig = plt.figure(figsize=(10,4))
plt.bar(range(df.Product_Category_1.nunique()),Category_Group,color = colors,width = 0.6)
for x,y in enumerate(Category_Group):
plt.text(x,y + 3,y,ha = 'center')
plt.xticks(range(df.Product_Category_1.nunique()),Category_Group.index)
plt.ylim(0,200)
plt.xlabel('类别',fontsize = 12)
plt.ylabel('销售额(百万美元)',fontsize = 12)
plt.title('不同分类销售额对比图',fontsize = 13)
plt.tight_layout()
plt.show()
#条形图不太方便,通过饼图来直观感受占比
plt.figure(figsize=(12,9))
plt.pie(x = Category_Group,colors = colors,radius = 1.5,wedgeprops = {'width':0.6,'edgecolor':'w'},\
autopct = '%.f%%',pctdistance = 0.8,labels = Category_Group.index)
plt.title('不同分类销售额对比图',y = 1.14,fontsize = 13)
plt.show()
Первая категория по объему продаж – 1, что составляет 188,3 млн долларов США, что составляет 38%.
Вторая и третья категории по объемам продаж занимают 5 и 8 места, на них приходится 18% и 17% продаж соответственно.
18, 9, 17, 12, 13 пять категорий продаж товаров менее 1 миллиона долларов США
Большая разница в продажах по категориям
# 箱型图 查看数据分布和异常值
fig = plt.figure(figsize=(14,6))
sns.boxplot(x = 'Product_Category_1',y = 'Purchase',data = df)
plt.tight_layout()
plt.title('不同类别商品销售单价箱线图',fontsize = 14)
plt.show()
Цены за единицу товаров категорий 1, 5 и 8 с наибольшим объемом продаж находятся в среднем или нижнем положении, что доказывает, что спрос на эти 3 категории товаров очень высок.
Категория 10 имеет самую высокую цену за единицу, но только 2% от объема продаж, а другие категории с более высокой ценой за единицу, как правило, не высоки.
Категории 12 и 13 имеют самую низкую цену за единицу и самые низкие продажи, менее 1 миллиона долларов США вместе взятые.
#结合商品类别和消费者性别进行分析,看一看男性和女性消费者的消费偏好
Category_Gender_pvt = pd.pivot_table(df,index = 'Product_Category_1',columns = 'Gender',\
values = 'Purchase',aggfunc = np.sum)
M_Percent = round(Category_Gender_pvt.M / df.groupby('Product_Category_1').Purchase.sum() *100,1)
F_Percent = round(100 - M_Percent,1)
fig = plt.figure(figsize=(12,4.5))
width_bar = 0.35
plt.bar(np.arange(18) - width_bar * 0.5,M_Percent,width = width_bar,color = colors[0],label = 'M')
for x1,y1 in enumerate(M_Percent):
plt.text(x1 - width_bar * 0.5,y1 + 2,y1,ha = 'center')
plt.bar(np.arange(18) + width_bar * 0.5,F_Percent,width = width_bar,color = colors[1],label = 'F')
for x2,y2 in enumerate(F_Percent):
plt.text(x2,y2 + 2,y2)
plt.xticks(np.arange(18),Category_Gender_pvt.index)
plt.xlim(-0.8,19)
plt.ylim(0,100)
plt.xlabel('类别',fontsize = 12)
plt.ylabel('百分比(%)',fontsize = 12)
plt.title('各类别男女销售额占比图',fontsize = 14)
plt.legend()
plt.tight_layout()
plt.show()
Категории с наибольшей долей мужского потребления — 17 и 18 лет, на которые приходится 89,6% и 88,2% соответственно.
Категории с самой высокой долей женского потребления — 14 и 12, на которые приходится 42,8% и 40,7% соответственно, и эта доля все еще ниже, чем у мужчин.
В самых продаваемых категориях 1, 5 и 8 мужчины тратят гораздо больше, чем женщины.
резюме
Мужчины доминируют в потреблении, молодые и неженатые люди среднего возраста обладают высокой покупательной способностью и могут использоваться в качестве целевого рынка Цена за единицу оказывает значительное влияние на продажи Различные продукты могут быть запущены в зависимости от условий населения разных городов, и точное размещение может максимизировать преимущества.