业务场景需求:
需求描述:
从HIVE中调取用户近三个月的充值失败信息,为每笔记录打上设备标识/累计充值/充值渠道/充值渠道标识等字段。
需求字段:
用户账号、行为时间、设备标识(ios/ad)、该用户本月累计充值、充值渠道、充值渠道标识
拆解:
- 设备标识字段:需要通过调取用户登录日志中的app_channel字段来识别,app_store为ios,其余为安卓。
- 该用户本月累计充值:需要调取用户充值日志中的每笔记录sum得出。
- 充值渠道:如充值失败表单中app_channel有ds记为ds,有sdk3rd记为web,其他记为other。
- 首先需要将用户登录档日志新建一列os_name,给用户打上标签。
- 将充值失败表单中新建一列channeltag,通过上述内容打上标签。
- 将三张表格进行一个类vlookup(join)的操作联合在一起,以充值失败为基准,匹配不到的地方留空。
- ps:游戏三端互通,需要以id前缀为主键
1.添加os_name
tempA=pd.read_csv(r'登录log.csv',sep=',',header=0)
tempA['Aid']=tempA['Aid'].str.split('@').str[0].str.split('.').str[0]
#对ID进行切割只保留前缀
tempA.loc[tempA['appchannel']=='app_store','os_name']='ios'
#打标ios
tempA['os_name'].fillna('ad',inplace=True)
#对其他未被打标为ios的填充为ad
resultA=pd.concat([tempA['Aid'],tempA['os_name']],axis=1)
#只保留id和标识两列
2.添加channeltag
tempB=pd.read_csv(r'充值失败.csv',sep=',',header=0)
tempB.loc[tempB['app_channel'].str.contains('ds'),'channeltag']='ds'
tempB.loc[tempB['app_channel'].str.contains('sdk3rd'),'channeltag']='web'
tempB['channeltag'].fillna('other',inplace=True)
resultB=pd.concat([tempB['Aid'],tempB['channeltag']],axis=1)
3.以Aid为主键完成类vlookup/left join的操作将三个表的字段连在一起
tempC=pd.read_csv(r'累计充值.csv',sep=',',header=0)
tempab=pd.merge(resultB,resulA.loc[:,['acc_id','os_name']],how='left',on='Aid')
result=pd.merge(tempab,tempC.loc[:,['Aid','cash']],how='left',on='Aid')
result.to_csv(r'XXX.csv',index=0)
用到的方法:
- 数据合并:pd.merge、pd.concat
pd.merge(left, right, how = ‘inner', on = None, left_on = None, right_on = None,
left_index = False, right_index = False, sort = True, suffixes = (‘_x','_y'),
copy = True, indicator = False, validate = None)
left、right:需要连接的两个DataFrame或Series,一左一右
how:两个数据连接方式,默认为inner,可设置inner、outer、left或right
on:作为连接键的字段,左右数据中都必须存在,否则需要用left_on和right_on来指定
left_on:左表的连接键字段
right_on:右表的连接键字段
left_index:为True时将左表的索引作为连接键,默认为False
right_index:为True时将右表的索引作为连接键,默认为False
suffixes:如果左右数据出现重复列,新数据表头会用此后缀进行区分,默认为_x和_y
pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,
keys=None, levels=None, names=None, verify_integrity=False,
copy=True)
obj:为Series、DataFrame、Pannel对象的序列或映射。
axis:默认为0。左右连接。1就是上下链接
join:{“inner”, “outer”},是为内连接和外连接。
keys:使用传递的键值,作为最外才能够构建层次索引。如果为多索引,应该使用元组。
- 空值填充:df.fillna()
DataFrame.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None, **kwargs)
value: 变量、字典、Series,DataFrame;用于填充填充缺失值,或指定为每个索引(对于Series)或列(对于DataFrame)的缺失值使用字典/Series/DataFrame的值填充
method: {‘backfill’, ‘bfill’, ‘pad’, ‘ffill’, None}, 默认None, pad/ffill表示向后填充空值,backfill/bfill表示向前填充空值
axis: {0 or ‘index’, 1 or ‘columns’}
inplace: boolean, 默认为False。若为True, 在原地填满
limit: int, 默认为None, 如果指定了方法, 则这是连续的NaN值的前向/后向填充的最大数量
downcast: dict, 默认None, 字典中的项为类型向下转换规则。
- 文本包含:df.str.contains()
Series.str.contains(pat,case = True,flags = 0,na = nan,regex = True)
>判断是否包含多值的写法:df['columnname'].str.contains('str1|str2')
pat : str类型,字符序列或正则表达式。
case : bool,默认为True,如果为True,区分大小写。
flags : int,默认为0(无标志),标志传递到re模块,例如re.IGNORECASE。
na : 默认NaN,填写缺失值的值。
regex : bool,默认为True;如果为True,则假定pat是正则表达式;如果为False,则将pat视为文字字符串。
- 数据选取:df.loc()