赞
踩
日常业务需求中,仅凭SQL一招鲜是没法吃遍天的,这个时候就需要更为强大的Python进行支持了。这个系列主要分享一些Python小案例,都是根据笔者日常工作需求抽离总结的,如有雷同,纯属巧合~
这一期,主要是利用python处理非结构化文本数据。而且每个小案例可能隐藏着一些使用的Pandas
技巧.
隐藏知识点:函数递归
# ⚠️注意:用`json.loads`处理json型字符串时,键值应用双引号,外围用单引号。否则会转换失败,这里只是简单处理,所以采用`eval`函数避免转换错误。
# 随机构造一个json型的字符串
s = "{'A':111,'B':{'2':'b','1':{'a':23,'b':34,'c':{'HH':'good','hhh':[3,2,'q']}},\
'3':[1,2,3]},'C':['a',34,{'mm':567,'gg':678}]}"
# 开发半展开json函数 def json_half_flat(dic): ''' 半展开json,只对字典类型展开 dic:字典 return:展开后的字典 ''' init_dic = {} keys = list(dic.keys()) for i in keys: init_dic_value = dic[i] if type(init_dic_value) == dict: init_dic_value = json_half_flat(init_dic_value) init_dic_keys = list(init_dic_value.keys()) for j in init_dic_keys: name = str(i) + '_' + str(j) init_dic[name] = init_dic_value[j] else: init_dic[i] = init_dic_value return init_dic # 开发全展开json函数 def json_flat(dic): ''' 全展开json,对字典、列表均进行展开 dic:字典 return:展开后的字典 ''' init_dic = {} keys = list(dic.keys()) for i in keys: init_dic_value = dic[i] if type(init_dic_value) == dict: init_dic_value = json_flat(init_dic_value) init_dic_keys = list(init_dic_value.keys()) for j in init_dic_keys: name = str(i) + '_' + str(j) init_dic[name] = init_dic_value[j] elif type(init_dic_value) == list: length = len(init_dic_value) for j in range(length): name = str(i) + '_' + str(j) init_dic[name] = init_dic_value[j] else: init_dic[i] = init_dic_value return init_dic
s2j = eval(s)
json_half_flat(s2j) # 下方输出结果可以发现半展开json函数对列表或者列表内的json不做处理
{'A': 111,
'B_2': 'b',
'B_1_a': 23,
'B_1_b': 34,
'B_1_c_HH': 'good',
'B_1_c_hhh': [3, 2, 'q'],
'B_3': [1, 2, 3],
'C': ['a', 34, {'mm': 567, 'gg': 678}]}
s2j = eval(s)
json_flat(s2j) # 下方输出结果可以发现全展开json会对所有的json和列表均进行展开
{'A': 111,
'B_2': 'b',
'B_1_a': 23,
'B_1_b': 34,
'B_1_c_HH': 'good',
'B_1_c_hhh_0': 3,
'B_1_c_hhh_1': 2,
'B_1_c_hhh_2': 'q',
'B_3_0': 1,
'B_3_1': 2,
'B_3_2': 3,
'C_0': 'a',
'C_1': 34,
'C_2': {'mm': 567, 'gg': 678}}
这里介绍可用于处理中文地址的cpca
库,甚至还具有自动补全地址省市的功能。
隐藏知识点:列表列拆分为多列
pip install cpca
import pandas as pd
import numpy as np
import cpca
# 构造地址数据df
df_address = pd.DataFrame(
{'id':[1,2,3],
'address':["徐汇区虹漕路461号58号楼5楼", "泉州市洛江区万安塘西工业区", "北京朝阳区北苑华贸城"]})
df_address
id | address | |
---|---|---|
0 | 1 | 徐汇区虹漕路461号58号楼5楼 |
1 | 2 | 泉州市洛江区万安塘西工业区 |
2 | 3 | 北京朝阳区北苑华贸城 |
def get_address(location_str): ''' 提取字符串的地址信息 location_str:地址字符串 return:省、市、区、地址、邮编 ''' location_str=[location_str] df = cpca.transform(location_str) try: p=df['省'].values[0] c=df['市'].values[0] d=df['区'].values[0] ad=df['地址'].values[0] adcode=df['adcode'].values[0] except: pass return p,c,d,ad,adcode
df_address['local'] = df_address['address'].apply(get_address)
df_address[['province', 'city', 'district', 'address', 'adcode']] = df_address['local'].apply(pd.Series) # 列表拆分为多列
df_address
id | address | local | province | city | district | adcode | |
---|---|---|---|---|---|---|---|
0 | 1 | 虹漕路461号58号楼5楼 | [上海市, 市辖区, 徐汇区, 虹漕路461号58号楼5楼, 310104] | 上海市 | 市辖区 | 徐汇区 | 310104 |
1 | 2 | 万安塘西工业区 | [福建省, 泉州市, 洛江区, 万安塘西工业区, 350504] | 福建省 | 泉州市 | 洛江区 | 350504 |
2 | 3 | 北苑华贸城 | [北京市, 市辖区, 朝阳区, 北苑华贸城, 110105] | 北京市 | 市辖区 | 朝阳区 | 110105 |
这里通过urlextract
库进行url提取,并通过正则过滤非图片url
隐藏知识点:列转多行
# !pip install urlextract
import pandas as pd
import numpy as np
import re
# 构造地址数据df
df_pic = pd.DataFrame(
{'id':[1,2],
'content':[
'src=\"https://sm-wick-question.oss-cn-zhangjiakou.aliyuncs.com/QuestionAnswerImage/64809-1276-question.jpg\"></div>", "answer": "<div> <img src=\"https://sm-wick-question.oss-cn-zhangjiakou.aliyuncs.com/QuestionAnswerImage/64809-1276-answer.jpg\"></div>"'
,'"avatar_url": "https://image.uc.cn/s/wemedia/s/upload/2021/5850c345e69483fd27b2622e9216273f.png", "description": "优秀青年教师", "fans_count": 0, "columns_count": 71, "courses_count": 0, "page_url": "https://course.myquark.cn/page/teacher?entrance=paisou_kgcard&page_name=page_a2s0k_course_learning&md_frm=teacher_area&uc_biz_str=qk_enable_gesture%3Afalse%7COPT%3ABACK_BTN_STYLE%400%7COPT%3AKEEP_SCREEN_ON%401%7COPT%3AW_PAGE_REFRESH%400%7COPT%3AS_BAR_BG_COLOR%40FFFFFF%7Cnull#/!{%22teacher_id%22:%22c099794880e34395b5bb146a1a04da99%22}", "cover_url": "http://image.uc.cn/s/wemedia/s/upload/2021/13078b26626a526e577585f6fc93430a.png"'
]})
df_pic
id | content | |
---|---|---|
0 | 1 | src="https://sm-wick-question.oss-cn-zhangjiak... |
1 | 2 | "avatar_url": "https://image.uc.cn/s/wemedia/s... |
# 提取url def get_urls(s): '''提取字符串的url s:字符串 return:url列表 ''' from urlextract import URLExtract extractor = URLExtract() urls = extractor.find_urls(s) return urls # 列转多行 def split_row(df, column): """ 拆分成多行 df: 原始数据 column: 拆分的列名 return: df """ row_len = list(map(len, df[column].values)) rows = [] for i in df.columns: if i == column: row = np.concatenate(df[i].values) else: row = np.repeat(df[i].values, row_len) rows.append(row) return pd.DataFrame(np.dstack(tuple(rows))[0], columns=df.columns)
# 提取urls
df_pic['urls'] = df_pic['content'].map(lambda x: get_urls(x))
# 列转多行
df_pic_result = split_row(df_pic, column='urls')
# 提取图片url
df_pic_result['pic'] = df_pic_result['urls'].map(lambda x: re.search('jpg|png', x, re.IGNORECASE))
df_pic_result = df_pic_result.dropna(subset=['pic']) # 删除没正则匹配到图片的数据
# 剔除尾部反斜杠、截取到jpg|png
df_pic_result['urls_new'] = df_pic_result['urls'].map(lambda x: re.search('http(.+?)(png|jpg)', x.rstrip('\\'), re.IGNORECASE).group(0))
# 展示结果
df_pic_result[['id', 'urls_new']]
id | urls_new | |
---|---|---|
0 | 1 | https://sm-wick-question.oss-cn-zhangjiakou.aliyuncs.com/QuestionAnswerImage/64809-1276-question.jpg |
1 | 1 | https://sm-wick-question.oss-cn-zhangjiakou.aliyuncs.com/QuestionAnswerImage/64809-1276-answer.jpg |
2 | 2 | https://image.uc.cn/s/wemedia/s/upload/2021/5850c345e69483fd27b2622e9216273f.png |
4 | 2 | http://image.uc.cn/s/wemedia/s/upload/2021/13078b26626a526e577585f6fc93430a.png |
利用正则过滤非中文,通过Python的Counter
进行统计。
import re from collections import Counter # 构造数据 s = ['asdk;*教师oq年教w%8青年教qw优秀asd;青年教师asd','教w%8青年教qw优秀a'] # 统计所有汉字 cn = Counter() for i in s: s_ch = re.sub('[^\u4e00-\u9fa5]+', '', i) # 剔除非中文 for j in s_ch: if j=='': continue cn[j]=cn[j]+1 # 输出结果 print('统计结果:',list(cn.items())) # 查看统计结果 print('统计结果Top2:',cn.most_common(2)) # 查看次数最高的2个汉字
统计结果: [('教', 6), ('师', 2), ('年', 4), ('青', 3), ('优', 2), ('秀', 2)]
统计结果Top2: [('教', 6), ('年', 4)]
Hive也能完成上述任务,主要我在当时没想到split(str,‘’)可以进行分隔声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。