产品经理数据分析不求人(3) - 拼团购数据清洗
产品经理数据分析不求人(2) - Pandas处理Excel
有了前两篇的基础,现在可以来看看如何通过简单的代码结合工作中的实际场景进行简单的分析,目标对象是团购数据。原本我想直连Hive取数,但是因为安全限制原因只能通过工具导出Excel再做进一步的分析。首先要考虑清楚通过数据分析希望得到什么结论,需要哪些字段作为输入条件,需要哪些字段验证猜想。拼团是一个社会化传播的行为,电商公司对商品进行让利补贴,并提供全场免邮,希望能带动新客实现首单的购买,所以这里有三个关键元素: 新客,商品,成本,成功的拼团活动应该是传播力强,新客占比高,拉新成本有效控制。
先从商品角度来看,根据不同的品类,品牌,价格,毛利等因素制定补贴规则,如9.9元抢购甚至1元拼团栏目之类商品补贴成本比较高,自然也希望能带来更多的新客。一方面我们可以考虑提升成团门槛,仅限新客成团,并增加成团人数,另一方面也可以考虑把珍稀资源分配给最有价值的用户,也就是拉新能力最强的用户。那么从用户角度来分析,什么样的用户拉新能力最强呢? 动动脚指头也能想到社交价值衰减规律会对拉新价值带来影响,如果一个用户多次参加拼团,反复刷洗自己的朋友圈,那么他能带来新客的概率就会很低了。除此之外还有哪些因素可能会影响到拼团的效果呢? 我们可以通过数据分析快速验证一下。
我需要的数据分为input(因子)和output(结果)两部分,因子可以有很多,但是真正有影响力的关键因子被埋藏在大量无效因子里面,我们必须把这些关键因子挖掘出来,有的因果关系并不是显而易见的,必须通过数据挖掘才能发现其中奥秘,比如用户手机剩余电量对转化率有戏剧性影响。再就是我所分析场景的核心KPI指标。对于拼团这个案例而言,用户相关因子可以有机型,注册时间,会员等级,性别,婚姻状态,地理位置,年龄,消费水平等等,可以有几百个变量,对于示例来说我们取十几个变量就够了。对于KPI指标,我会关注成团数和最关键的拉新人数。
以下是我选出来可用的字段,group_count和new_user_count分别是成团数和拉新人数,birthday和reg_time我用来衍生转化为其他字段,其余的都是可以直接使用的因子。
我拿到了十几万数据来做聚类分析,统计前要对原始数据加工清洗一下,首先我发现星座这个字段的值是错的,居然有70多个不同的值。这没关系,可以直接从生日中的月和日来推算,先写一个转化函数。稍微简单说明一下, u前缀表示字符是一个unicode对象,否则中文会乱码。lambda是匿名函数的写法,输入是日期,如果这个日期大于month, day则返回True, 否则返回False. filter对range序列中的元素依次执行前面的匿名函数,将执行结果为True的元素组成一个List返回。如果有兴趣可以google一下具体了解细节,不想了解也没关系,把下面的函数拷贝到代码中直接使用即可。
Tips: 我们开始用到了函数定义,首行结尾必须有个冒号,函数体必须保持一个同样的缩进(tab), 否则语法解析器会报错。
def derive_horoscope(month, day):
value = (u'摩羯座',u'水瓶座',u'双鱼座',u'白羊座',u'金牛座',u'双子座',u'巨蟹座',u'狮子座',u'处女座',u'天秤座',u'天蝎座',u'射手座')
range = ((1,20),(2,19),(3,21),(4,21),(5,21),(6,22),(7,23),(8,23),(9,23),(10,23),(11,23),(12,23))
seq = list(filter(lambda date:date<=(month,day), range))
return value[len(seq)%12]
既然修复了星座,也可以从生日中的年份计算出生肖, 这个函数更简单
def derive_zodiac(year):
return u'猴鸡狗猪鼠牛虎兔龙蛇马羊' [year%12]
接下来我们要从生日得出年龄,为了方便做聚类统计,我希望把不同年龄映射到四组年龄段,需要先导入一个时间库datetime
import pandas as pd
import datetime
from dateutil.parser import parse
def derive_age_range(year):
age = datetime.datetime.now().year - year
value = ('20-', '20s', '30s', '40+')
range = (0, 20, 30, 40)
seq = list(filter(lambda x:x<=age, range))
return value[len(seq)-1]
最后我还要根据用户的注册时间推算出用户使用应用的年限,同样也映射到六个时间段
def derive_register_interval(year, month):
year_diff = datetime.datetime.now().year - year
month_diff = datetime.datetime.now().month - month
interval = year_diff*12 + month_diffvalue = (u'三个月内', u'三到六个月', u'半年到一年', u'一年到两年', u'两年到三年', u'三年以上')
range = (0, 3, 6, 12, 24, 36)
seq = list(filter(lambda x:x<interval), range)
return value[len(seq)-1]
现在我们终于可以put everything together, 调用上面的四个方法实现完整的数据转化逻辑了。
from dateutil.parser import parse
#检查日期是否合法
def is_date(string):
try:
parse(string.strftime('%Y-%m-%d'))
return True
except Exception:
return False### 这里拷贝粘贴前面的四个函数进来 ###
#定义数据源和临时文件输出路径
input_file = "d:/dev/groupon_raw_data.xlsx"
output_file = "d:/dev/groupon_tmp.xlsx"df = pd.read_excel(input_file)
#从生日和注册时间推算出新的所需字段
horoscope = []
zodiac = []
age_range = []
interval = []
for index, row in df.iterrows():
bday = row['birthday']
if (is_date(bday)):
horoscope.append(derive_horoscope(bday.month, bday.day))
zodiac.append(derive_zodiac(bday.year))
age_range.append(derive_age_range(bday.year))
else:
horoscope.append("n/a")
zodiac.append("n/a")
age.append("n/a")reg_time = row['reg_time']
if (is_date(reg_time)):
interval.append(derive_register_interval(reg_time.year, reg_time.month))
else:
interval.append("n/a")#丢弃掉错误的星座字段并新增推算出来的衍生字段
df.drop(['horoscope'], axis = 1, inplace = True)
df.insert(loc=4, column='horoscope', value=horoscope)
df.insert(loc=5, column='zodiac', value=zodiac)
df.insert(loc=6, column='age_range', value=age_range)
df.insert(loc=7, column='interval', value=interval)#将转化后的数据写入临时文件
writer = pd.ExcelWriter(output_file)
df.to_excel(writer,'Sheet1',index=False)
writer.save()print("Raw data processing completed!")
出于安全考虑原数据就不提供了,下一次我们将利用这个临时文件做简单的聚类分析,并以可视化方式呈现结论