引入使用的包

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import sklearn as sk
%matplotlib inline
import datetime
import os
import seaborn as sns

读取文件

train = pd.read_csv("train_users_2.csv")
test = pd.read_csv("test_users.csv")

观察数据

1.数据含义
train.head(5)

test.head(5)


从train和test文件中观察到数据train有16个feature,test有15个feature,
其中是因为test文件中少了country_destination(订房国家)这一feature,也是我们需要去预测的。
前面15个feature的含义分别是:

feature 含义
id 用户的id
date_account_created 账号生成时间
timestamp_first_active 账号激活时间
data_first_booking 第一次订房时间
gender 性别
age 年龄
signup_method 注册方式
language 使用的语言
affiliate_channel 付费市场渠道
affiliate_provider 付费市场渠道名称
first_affiliate_tracked 注册前第一个接触的市场渠道
signup_app 注册的app
first_device_type 设备类型
first_brower 浏览器类型
2.观察一下数据量的大小类型和缺失值情况
print(train.shape)
print(test.shape)

print(train.info())
print('-----------------------------------------')
print(train.isnull().sum(axis=0))

print(test.info())
print('-----------------------------------------')
print(test.isnull().sum(axis=0))


从数据大小上来看:train中共有213451条数据,test里共有62096条数据。
从空值上来看:2个数据集都分别在一些feature中有空值的情况,分别是:

空值特征数量 train test
date_first_booking 124543 62096
age 87990 28876
first_affiliate_tracked 6065 20

从数据类型上来:date_account_created,timestamp_first_active,date_first_booking数据类型分别是object,int64和object。
但是通过我们仔细观察数据,这三个feature都是描述时间的,所以我们考虑把它们转换为datatime格式的来操作。

数据探索

date-accout_created(账号注册生成时间)
print(train.date_account_created.value_counts())
print(train.date_account_created.value_counts().describe())
print(test.date_account_created.value_counts())
print(test.date_account_created.value_counts().describe())

把汇总后可以发现:
看起来数据基本正常,没有异常值
train dataset里的账号生成时间分布在1634个不同的天数内,大约是四年半;test dataset里分布了92个不同的天数,大概3个月。
而且看起来train dataset里的天数显示是从2010年到2014年5月,而恰好test dataset里显示从2014年7月开始,那么我们可以猜测这俩个数据集或许就是依赖账号生成时间而进行分割的。我们需要证明我们的猜想。
首先来看一下时间线是不是按照我们想想的情况发生的:
这里我们需要先把数据的类型进行转换,用pandas的to_datetime()函数把其转换成时间数据类型,这样我们能更容易看出数据的情况:

train["date_account_created"] = pd.to_datetime(train.date_account_created)
test["date_account_created"]= pd.to_datetime(test.date_account_created)
print ("Train数据显示第一天: {},最后一天:{}".format(train.date_account_created.min(),train.date_account_created.max()))
print ("Test数据显示第一天: {},最后一天:{}".format(test.date_account_created.min(),test.date_account_created.max()))

Train数据显示第一天: 2010-01-01 00:00:00,最后一天:2014-06-30 00:00:00
Test数据显示第一天: 2014-07-01 00:00:00,最后一天:2014-09-30 00:00:00
利用datetime后转变的时间类型我们可以直接进行画图,看一下随着日期的变动每天的date_account_created用户注册量有怎样的呈现。

sns.set_style('whitegrid')
fig = plt.figure(figsize=(12, 6))
train.date_account_created.value_counts().plot('line')
test.date_account_created.value_counts().plot('line')
plt.xlabel('Year')
plt.ylabel('Count created')
plt.title('Accounts created vs Year')


我们可以看到随着时间的推移,账户的注册量越来越多,这一点证明了Airbnb的注册新用户是一个非常好的线性增长。
同时我们需要注意有一些峰值的出现,是否说明订房日期和节假日星期天等有所关联呢?我们还需要看到一个根据星期天来划分的feature。

timestamp_first_active(账号激活时间)

我们还是首先观察数据类型,我们记得timestamp_first_active数据看起来像是一个时间记录的数据,不过它是一个object类型,我们需要转换。

print(train.timestamp_first_active.value_counts())
print(train.timestamp_first_active.value_counts().describe())
print(test.timestamp_first_active.value_counts())
print(test.timestamp_first_active.value_counts().describe())


我们可以发现每一个通过这样观察每一个数据都是一个比较独立的values,看起来是年月日时分秒的一个形式,那么我们需要转换一下

train['date_first_active'] = pd.to_datetime(train.timestamp_first_active // 1000000, format = '%Y%m%d')
test['date_first_active'] = pd.to_datetime(test.timestamp_first_active // 1000000, format = '%Y%m%d')

再接着检查数据:

#类型检查
train.dtypes
#值检查
print(train.date_first_active.value_counts())
print(train.date_first_active.value_counts().describe())
#空值检查
train.date_first_active.isnull().sum()
#值检查
print(test.date_first_active.value_counts())
print(test.date_first_active.value_counts().describe())

好了我们给把时间戳形式的这一类数据转换成了时间类型的数据,然后确定数据数值基本没有异常,进行画图。

sns.set_style('whitegrid')
plt.figure(figsize=(12, 6))
train.date_first_active.value_counts().plot('line')
test.date_first_active.value_counts().plot('line')
plt.xlabel('Year')
plt.ylabel('First actived')
plt.title("First actived vs Year")


可以发现timestamp_first_active和date_account_created数据表现基本类似。都是随着时间的推移,注册量和激活量显著增加。同样存在峰值,在做特征工程的时候需要注意把时间这部分数据分成几个小的feature。

data_first_booking(第一次订房时间)
train.date_first_booking.describe()
test.date_first_booking.describe()



第一次订房时间在train里存在一半以上的空值,在test dataset里更是全部是空值,怕由于我们改动给未来模型增加noise,所以我们会选择删除这个feature。

gender(性别)

我们之前观察性别里有存在unknown的情况,那我们先看一下这一feature下有几个类型的数据。

print('Train dataset中性别分布为:\n ',  train.gender.value_counts(dropna = False))
print('Test dataset中性别分布为:\n ',test.gender.value_counts(dropna = False))


unknown的值有很多,尝试把它们变成空值进行处理。

train.gender.replace('-unknown-', np.nan, inplace=True)
test.gender.replace('-unknown-', np.nan, inplace=True)
sns.set_style('ticks')
plt.figure(figsize=(8, 6))
plt.subplot(1,2,1)
plt.bar(train.gender.value_counts().index,train.gender.value_counts(),color=['#073515','#327353','#107850','#529214'])
for i in range(3):dd = train.gender.value_counts().index[i]ff = train.gender.value_counts().values[i]plt.text(dd,ff+50,'%.0f' % ff, ha='center', va='bottom', fontsize=10)
plt.xlabel('Gender')
plt.ylabel('Number')
plt.title("Train dataset")
plt.subplot(1,2,2)
plt.bar(test.gender.value_counts().index,test.gender.value_counts(),color=['#073515','#327353','#107850','#529214'])
for i in range(3):dd = test.gender.value_counts().index[i]ff = test.gender.value_counts().values[i]plt.text(dd,ff+50,'%.0f' % ff, ha='center', va='bottom', fontsize=10)
plt.xlabel('Gender')
plt.ylabel('Number')
plt.title("Test dataset")plt.subplots_adjust(left=0.04, top=0.96, right = 0.96, bottom = 0.04)


我们用柱状图可视化一下,画图的步骤可能有些繁琐,以后加以改进。通过图中我们可以看出除了空值的话,女性比男性要多一些,那么我们也想到了各个国家的风俗习惯可能会有所差异,一起去旅游度假的时候,有的国家男性订房比较多,有的国家女性来掌管这项事务,我们针对于性别和订房国家来看一下他们之间的关系。又由于我们的数据条件下,训练集中有订房国家,所以这里我们只采用训练集来看一下这俩个特征之间的关系情况。

plt.figure(figsize=(10, 6))
female = sum(train.gender == 'FEMALE')
male = sum(train.gender == 'MALE')
other = sum(train.gender == 'OTHER')
Nan = sum(train.gender.isnull())female_destinations = train.loc[train.gender == 'FEMALE', 'country_destination'].value_counts()/female *100
male_destinations = train.loc[train.gender == 'MALE', 'country_destination'].value_counts() /male *100
other_destinations = train.loc[train.gender == 'OTHER', 'country_destination'].value_counts()/other*100
nan_destinations = train.loc[train.gender.isnull(), 'country_destination'].value_counts()/Nan*100 female_destinations.plot('bar', width = 0.15, color =  '#FF8B8B', position = 0, label = 'Female', rot = 0)
male_destinations.plot('bar', width = 0.15, color = '#0E38B1', position = 1, label = 'Male', rot = 0)
other_destinations.plot('bar', width = 0.15, color =  '#61BFAD', position = 2, label = 'Other', rot = 0)
nan_destinations.plot('bar', width = 0.15, color =  '#61145D',position = 3, label = 'Nan', rot = 0)plt.legend()
plt.xlabel('Destination Country')
plt.ylabel('Percentage Of Booking')
plt.show()


结论并不如我们期待那么乐观,基本上男女订房比例是在一个相似的水平没有很明显的区别,F(Not Destination Found;无目的地)这一类别中空值比例很高

Age(年龄)

我们之前查看空值的时候记得age在train和test里面都有空值的情况,我们再来看一下数据描述。

print(train.age.value_counts())
print(train.age.describe())
print(test.age.value_counts())
print(test.age.describe())

出现了最大年龄2014,2002的值,这一点数据异常值很多,我们猜测是把出发日期或者是出生日期填错了,根据我们的经验我们需要年龄设置一个有效区间。
根据人类最长寿命者Jeanne Calment的122岁到18岁的合法身份,我们先观察一下异常数据情况:

print('Train中Age异常值:')
print(sum(train.age>122)+sum(train.age<18))
print('Test中Age异常值:')
print(sum(test.age>122)+sum(test.age<18))

print(train[train.age > 122]['age'].describe())
print(test[test.age > 122]['age'].describe())

pd.set_option('display.max_columns',1000)
pd.set_option('display.max_rows',300)

25/50/75分位数显示Train中2014这个值比较多,和我们猜想填错注册时间基本验证,训练集是从2010年的数据开始那么我们看一下age大于2009的有多少:

train[train.age > 2009].age


占据异常值的大部分,我们把它们转换为空值后,我们再看一下其他大于122岁的:

train.loc[train.age > 2009, 'age'] = np.nan
train[train.age > 122].age


除了150和132这俩个数据比较特殊外,其他的数据像是出生年份,我们用Train中平均注册年份2012来减去这异常值,还原年龄。

train.age[train.age>122]= train.age[train.age>122].apply(lambda x:2012-x)

对于test数据用类似的方法,数据产生的日期年份(2014年)减去这一类异常值,还原年龄:

test.age[test.age>122]= test.age[test.age>122].apply(lambda x:2014-x)

看一下小于18岁的异常值:

print(train[train.age <18]['age'].describe())

print(test[test.age <18]['age'].describe())


从train和test数据表示16岁以上订房人群在平台或许是被准许的,所以我们可以把区间订的下限再降低一些。 我们可以根据常识再最后把年龄数据大于95,小于13的转换为空值:

train.loc[train.age > 95, 'age'] = np.nan
train.loc[train.age < 13, 'age'] = np.nan
test.loc[test.age > 95, 'age'] = np.nan
test.loc[test.age < 13, 'age'] = np.nan

我们将处理好的Age年龄数据可视化一下,看一下分布情况:

sns.set_style('ticks')
plt.figure(figsize=(20, 6))
plt.subplot(1,2,1)
sns.distplot(train.age.dropna(), color='#FD5C64')
plt.xlabel('Train Age')
sns.despine()
plt.subplot(1,2,2)
sns.distplot(test.age.dropna(), color='#055A5B')
plt.xlabel('Test Age')
sns.despine()


从上图可以看出明显订房年龄在25岁到40岁中间人数最多。那么我们再看一下年轻人和老年人是否对于目的地有所不同呢?我们用45岁来区别一下老年人和年轻人:

age = 45
width = 0.4
plt.figure(figsize=(10, 6))younger = sum(train.loc[train['age'] < age, 'country_destination'].value_counts())
older = sum(train.loc[train['age'] > age, 'country_destination'].value_counts())younger_destinations = train.loc[train['age'] < age, 'country_destination'].value_counts()/younger * 100
older_destinations = train.loc[train['age'] > age, 'country_destination'].value_counts()/older * 100younger_destinations.plot(kind='bar',width = 0.4, color='#20AD65', position=0, label='Youngers', rot=0)
older_destinations.plot(kind='bar', width = 0.4,color='#3A745F', position=1, label='Olders', rot=0)plt.legend()
plt.xlabel('Destination Country')
plt.ylabel('Percentage')sns.despine()
plt.show()

print(train.age.isnull().value_counts())
print(test.age.isnull().value_counts())


按照45岁来区分的话,可以看出年轻人更多选择在美国旅行,老人出国旅行的意愿更强烈。但是我们还是要记得在年龄数据中大概有45%的空值。

Signup_method(注册方式)
print(train.signup_method.value_counts())
print(test.signup_method.value_counts())


关于注册方式明显是一个分类的feature,看出大多数是basic,自建站的意思,我们可视化一下:

plt.figure(figsize=(10, 6))plt.subplot(1,2,1)
train.signup_method.value_counts().plot(kind='bar',color='#FB9B2A')plt.subplot(1,2,2)
test.signup_method.value_counts().plot(kind='bar',color='#674B74')


weibo 应该是中国注册的,其余这一feature没有缺失值,也没有异常值。

Signup_flow(注册页面)
print(train.signup_flow.value_counts())
print(test.signup_flow.value_counts())


我们能看到用户从各个不同的页面进入到注册页面进行注册的,有很多个类别,大多数是代号‘0’的页面。

plt.figure(figsize=(10, 6))plt.subplot(1,2,1)
train.signup_flow.value_counts().plot(kind='bar',color='#FB9B2A')plt.subplot(1,2,2)
test.signup_flow.value_counts().plot(kind='bar',color='#674B74')

Language(语言)
print(train.language.value_counts())
print(test.language.value_counts())

既然想要预测客户在哪里订房,语言这一特征必然起到很大作用,我们可以看一下。

plt.figure(figsize=(15, 6))plt.subplot(1,2,1)
train.language.value_counts().plot(kind='bar',color='#FB9B2A')plt.subplot(1,2,2)
test.language.value_counts().plot(kind='bar',color='#674B74')


基本上大多数是使用英语,这也在我们意料之中,毕竟Airbnb在United Stated本国推广程度更高一些。

Affiliate_Channel (付费市场渠道)
print(train.affiliate_channel.value_counts())
print(test.affiliate_channel.value_counts())

plt.figure(figsize=(15, 6))plt.subplot(1,2,1)
train.affiliate_channel.value_counts().plot(kind='bar',color='#FB9B2A')plt.subplot(1,2,2)
test.affiliate_channel.value_counts().plot(kind='bar',color='#674B74')


各种引流渠道中,大多数是直接的用户引流过来的

Affiliate_Provider (付费市场渠道名称)
print(train.affiliate_provider.value_counts())
print(test.affiliate_provider.value_counts())
plt.figure(figsize=(15, 6))plt.subplot(1,2,1)
train.affiliate_provider.value_counts().plot(kind='bar',color='#FB9B2A')plt.subplot(1,2,2)
test.affiliate_provider.value_counts().plot(kind='bar',color='#674B74')


除了直接过来的客户外,google引流渠道的效果很不错

First_Affiliate_Tracked (注册前第一个接触的市场渠道)
train.first_affiliate_tracked.isnull().sum()
test.first_affiliate_tracked.isnull().sum()
print(train.first_affiliate_tracked.value_counts())
print(test.first_affiliate_tracked.value_counts())

plt.figure(figsize=(15, 6))plt.subplot(1,2,1)
train.first_affiliate_tracked.value_counts().plot(kind='bar',color='#FB9B2A')plt.subplot(1,2,2)
test.first_affiliate_tracked.value_counts().plot(kind='bar',color='#674B74')


没接触过占大多数,其余的在lined(领英)上获取消息的比较多。

Signup_App(注册APP)
print(train.signup_app.value_counts())
print(test.signup_app.value_counts())

plt.figure(figsize=(15, 6))plt.subplot(1,2,1)
train.signup_app.value_counts().plot(kind='bar',color='#FB9B2A')plt.subplot(1,2,2)
test.signup_app.value_counts().plot(kind='bar',color='#674B74')


可以发现大多数使用Web端登陆的。

First_Device_Type(设备类型)
print(train.first_device_type.value_counts())
print(test.first_device_type.value_counts())

plt.figure(figsize=(15, 6))plt.subplot(1,2,1)
train.first_device_type.value_counts().plot(kind='bar',color='#FB9B2A')plt.subplot(1,2,2)
test.first_device_type.value_counts().plot(kind='bar',color='#674B74')


台式苹果的使用度比较高,而且苹果系列产品使用情况都挺高的

First_Browser (浏览器类型)
print(train.first_browser.value_counts())
print(test.first_browser.value_counts())
plt.figure(figsize=(20, 5))
plt.subplot(1,2,1)
train.first_browser.value_counts().plot(kind='bar',color='#FB9B2A')plt.subplot(1,2,2)
test.first_browser.value_counts().plot(kind='bar',color='#674B74')


我们这个train.csv数据探索就结束啦~

【Data Analysis 01】Airbnb_new_user_booking_DataExploration(爱彼迎新用户订房数据探索)相关推荐

  1. 考研订房攻略出炉!这是你现在能为初试做的最重要的事!

    01 哪些考生需要提前订房? 1. 异地考试的考生 在异地考试的小伙伴是最辛苦的,一定要提前订房,当然车票也必须提前预定.条件允许的话,可以提前几天过去,看考场之余,先适应一下环境,再选几家吃着舒服的 ...

  2. Python for Data Analysis

    本文只是一篇类似导向性的分享, 并没有原创内容, 主要是书籍和网络资源的整理, 仅供参考. 可能会有后续补充更新. 资源 A Byte of Python 这是给没有使用过 Python 的人员的入门 ...

  3. 转录组分析综述A survey of best practices for RNA-seq data analysis

    转录组分析综述 转录组 文献解读 Trinity cufflinks 转录组研究综述文章解读 今天介绍下小编最近阅读的关于RNA-seq分析的文章,文章发在Genome Biology 上的A sur ...

  4. python学习笔记(Data Analysis)

    Python for Data Analysis numpy基础 嗯 调整了一些顺序 1 ndarray(n维数组) 导入数据.基本运算和数组生成 import numpy as np #矢量化 将数 ...

  5. 拓扑数据分析-Topological data analysis

    一.拓扑概念 拓扑主要研究的对象为几何图形或空间结构,探究在连续改变形状后还能保持不变的一些性质.它只考虑物体间的位置关系而不考虑它们的形状和大小.简单的描述为:一些特殊的几何性质,在图形连续改变形状 ...

  6. Data Analysis 软件(色谱质谱图分析软件)安装步骤

    1.点击Agilent--GC-MS安装程序--GCMS E.02.01--Support--Agilent IO Libraries--双击setup.exe 安装(如果不能自动安装C++, vcr ...

  7. Topological Data Analysis(TDA) 拓扑数据分析与mapper算法

    目录 什么是TDA? mapper算法的大致流程 使用mapper进行数据分析的优点 参考连接 什么是TDA? 即对数据拓扑学特征进行分析的方法,那么什么是拓扑学特征?拓扑是研究几何图形或空间在连续改 ...

  8. python 数据分析 百度网盘_[百度网盘]利用Python进行数据分析(Python For Data Analysis中文版).pdf - Jan-My31的博客 - 磁力点点...

    利用Python进行数据分析(Python For Data Analysis中文版).pdf - Jan-My31的博客 2018-5-27 · 链接:https://pan.baidu.com/s ...

  9. 【CookBook pandas】学习笔记第五章 Exploratory Data Analysis

    dive more into - 深入讨论 exploratory data analysis , the process of sifting through the data and trying ...

最新文章

  1. nginx或httpd实现负载均衡tomcat(三)
  2. 【BIO】基于BIO实现简单动态HTTP服务器
  3. mysql mof_mof提权
  4. Golang 数组传参
  5. springboot 第四讲
  6. sql union 与多个order by 一起使用
  7. php能转换音频采样率吗,音频采样频率怎么设置-音频采样率转换软件下载
  8. IT的2017,面临数字生态系统新挑战,该怎么办?
  9. 自学python买什么书比较好-python入门学习哪个书比较好(python视频教程知乎)
  10. oracle no expand,NO_EXPAND Hint性能优化一例
  11. Java经典实例:实现一个简单堆栈
  12. 暴力破解之NTscan+密码字典工具
  13. 这40份酷炫的 Python 可视化大屏,简直太爱了
  14. 如何高效率的使用Google搜索
  15. Rxjava2中Single的just操作符源码学习
  16. Emacs配置管理框架Cabbage – 介绍
  17. 面试官:来写个代码求一下两个数的最大公约数吧
  18. ASC文件 - CAN报文回放
  19. BLE-2の蓝牙4.0协议栈のLL层 Scaning 和 initiating状态的区别
  20. Android开发中所需颜色的RGB值

热门文章

  1. python 中文转拼音原理_Python中文转拼音
  2. 跟这台计算机连接的一个USB设备运行不正常
  3. TTL(RGB)接口液晶显示屏的调试方法
  4. OracleBBED工具说明
  5. Web 和http协议
  6. 2021-02-14
  7. linux usb外接硬盘,在Linux系统上使用外置USB硬盘
  8. python列表题目_Python列表练习题
  9. 天嵌i.mx6q开发板android4.3编译问题
  10. Photoshop中裁剪工具的使用及扩展