Python|字符串数据清洗+分组计算

Table of Contents

问题背景

最近在某互联网公司实习,leader提了需求要处理一个数据,原始数据长这个样子(注:为了数据隐私,已进行加密处理)
原始数据
需求是这个样子的:

  • 需求1:将interests_news进行切分开成一条一条的,先处理一种情况:如果反斜杠只取反斜杠后面的标签,也就是二级标签。处理完成之后,如果是逗号连接,具体如下:每一个标签形成一行,后面对应三个变量保持一致。
  • 处理ok后的数据结构如下:
    初步处理后
  • 需求2:根据上述结果进行分组计算,也即根据兴趣点标签进行groupby 算users、ret_users的总和 以及两个变量的比值
  • 最终结果如下:
    最终结果

总结遇到的坑

  • 字符串处理 用replace的时候 单引号要用双引号去引 不能单引号再引单引号
  • groupby的时候如果少了元素 如果方法没问题 那就是数据的坑 比如字符串有的多了空格 有的没有空格 那就不一样了
  • 要考虑情况更加全面一点

导入相应的库+定义函数

import pandas as pd
import copy
import time

# 函数作用:反斜杠连接的多个元素取斜杠后面的一个元素
# 增加一个判断 如果有多个元素 且有多个反斜杠 均要去考虑
def f1(x):
    s = x.split(',')
#     print(s)
    n = len(s)
    for i in range(n):
        if '/' in s[i]:
            s[i] = s[i].split('/')[1]
    return s

处理流程

读入数据

data = pd.read_excel('./兴趣点.xlsx', sheet_name='Sheet2')
data = data.dropna()
print(data.shape)
data.head()
(42934, 5)
dayinterests_newsusersret_users次留
120190311["娱乐/明星八卦"]363.82995720870.521120
220190311["健康/养生"]27.4695836020.398086
320190311["娱乐/明星八卦","娱乐"]411.8949764750.025857
420190311["体育/NBA"]47.8314494320.058352
520190311["社会"]183.3162484010.103651

筛选数据

data_10 = data[data['users'] > 5]
# 重新设置索引
data_10 = data_10.reset_index(drop=True)
print(data_10.shape)
data_10.head()
(403, 5)
dayinterests_newsusersret_users次留
020190311["娱乐/明星八卦"]363.82995720870.521120
120190311["健康/养生"]27.4695836020.398086
220190311["娱乐/明星八卦","娱乐"]411.8949764750.025857
320190311["体育/NBA"]47.8314494320.058352
420190311["社会"]183.3162484010.103651

字符串处理

# 先拷贝下数据
df = copy.deepcopy(data_10)
df['interests_news'] = df['interests_news'].apply(lambda x: x.replace('[', '').replace(']', '').replace('"', ''))
df['interests_news'] = df['interests_news'].map(f1).map(str)
df['interests_news'] = df['interests_news'].apply(lambda x: x.replace('[', '').replace(']', '').replace("'", ''))
print(df.shape)
df.head()
(403, 5)
dayinterests_newsusersret_users次留
020190311明星八卦363.82995720870.521120
120190311养生27.4695836020.398086
220190311明星八卦, 娱乐411.8949764750.025857
320190311NBA47.8314494320.058352
420190311社会183.3162484010.103651

对兴趣点变量进行拆分

思路梳理:

  • 其实就是一个DataFrame的拼接,定义几个空list 然后对应的内容放进去 每次都形成一个新的DataFrame 形成过程先把数值不同的放在一起
  • 把所有的DataFrame都放到一个list 最后进行concat
# 思路:其实就是一个数据框的拼接 分别每次形成一个数据框
# 先定一个空列表
data_need = []
for i in range(len(df)):
    # 每次循环都清空兴趣点列表
    int_news = []
    # 根据逗号进行切分
    s = df['interests_news'][i].split(',')
#     print(s)
#     break
    # 计算兴趣点词条的个数
    n = len(s)
    for j in range(n):
        # 将所有兴趣点内容放到一个list
        int_news.append(s[j])
    # 形成数据框
    y = pd.DataFrame({'interests_news': int_news})
    # 补充其余三列相同的信息
    y['users'] = df['users'][i]
    y['ret_users'] = df['ret_users'][i]
    y['次留'] = df['次留'][i]
    # 单个数据框ok之后放到list中 
    data_need.append(y)
# 一起concat
data_new = pd.concat(data_need, axis = 0)
print(data_new.shape)
data_new.head()
(934, 4)
interests_newsusersret_users次留
0明星八卦363.82995720870.521120
0养生27.4695836020.398086
0明星八卦411.8949764750.025857
1娱乐411.8949764750.025857
0NBA47.8314494320.058352

分组计算

思路梳理:

  • 先进行groupby
  • 然后对分组后的结果进行循环 然后再对每个子块进行求和等等 结果都放到一个list里面去 然后构建字典 形成DataFrame
  • 最后进行一个合并
# 重新设置索引
data_new = data_new.reset_index(drop=True)
# 删空格 后面groupby发现的坑
data_new['interests_news'] = data_new['interests_news'].apply(lambda x: x.strip())
# 定义四个空列表 用来装每次分组计算的变量
interests_news = []
users = []
ret_users = []
ratio = []
# 进行groupby
dg1 = data_new.groupby('interests_news')
# 循环进行计算
for i in dg1:
    interests_news.append(i[0])
    users.append(i[1]['users'].sum())
    ret_users.append(i[1]['ret_users'].sum())
    ratio.append(i[1]['ret_users'].sum() / i[1]['users'].sum())
# 构建数据框
y = pd.DataFrame({'interests_news': interests_news, 
                 'users': users,
                 'ret_users': ret_users,
                 'ratio': ratio})
# 输出
y.to_csv('大于5的用户数分组计算结果.csv', index = False, encoding='gbk')
print(y.shape)
y.head()
(102, 4)
interests_newsusersret_usersratio
0CBA173.7070812561.473745
1NBA392.7998308842.250510
2三农87.064592911.045201
3世界史67.310528480.713113
4两性421.0346834050.961916

封装成函数

import pandas as pd
import copy
import time

# 函数作用:反斜杠连接的多个元素取斜杠后面的一个元素
# 增加一个判断 如果有多个元素 且有多个反斜杠 均要去考虑
def f1(x):
    s = x.split(',')
#     print(s)
    n = len(s)
    for i in range(n):
        if '/' in s[i]:
            s[i] = s[i].split('/')[1]
    return s

def Cleandata():
    t0 = time.time()
    # 1 读入数据
    data = pd.read_excel('./兴趣点.xlsx', sheet_name='Sheet2')
    data = data.dropna()
    print(data.shape)
    data.head()
    # 2 筛选数据
    data_10 = data[data['users'] > 5]
    # 重新设置索引
    data_10 = data_10.reset_index(drop=True)
    print(data_10.shape)
    # 3 字符串处理
    # 先拷贝下数据
    df = copy.deepcopy(data_10)
    df.head()
    df['interests_news'] = df['interests_news'].apply(lambda x: x.replace('[', '').replace(']', '').replace('"', ''))
    df['interests_news'] = df['interests_news'].map(f1).map(str)
    df['interests_news'] = df['interests_news'].apply(lambda x: x.replace('[', '').replace(']', '').replace("'", ''))
    # 4 对兴趣点变量进行拆分
    # 思路:其实就是一个数据框的拼接 分别每次形成一个数据框
    # 先定一个空列表
    data_need = []
    for i in range(len(df)):
        # 每次循环都清空兴趣点列表
        int_news = []
        # 根据逗号进行切分
        s = df['interests_news'][i].split(',')
        # 计算兴趣点词条的个数
        n = len(s)
        for j in range(n):
            # 将所有兴趣点内容放到一个list
            int_news.append(s[j])
        # 形成数据框
        y = pd.DataFrame({'interests_news': int_news})
        # 补充其余三列相同的信息
        y['users'] = df['users'][i]
        y['ret_users'] = df['ret_users'][i]
        y['次留'] = df['次留'][i]
        # 单个数据框ok之后放到list中 
        data_need.append(y)
    # 一起concat
    data_new = pd.concat(data_need, axis = 0)
    print(data_new.shape)
    data_new.head()
    # 5 分组计算
    # 重新设置索引
    data_new = data_new.reset_index(drop=True)
    # 删空格 后面groupby发现的坑
    data_new['interests_news'] = data_new['interests_news'].apply(lambda x: x.strip())
    # 定义四个空列表 用来装每次分组计算的变量
    interests_news = []
    users = []
    ret_users = []
    ratio = []
    # 进行groupby
    dg1 = data_new.groupby('interests_news')
    # 循环进行计算
    for i in dg1:
        interests_news.append(i[0])
        users.append(i[1]['users'].sum())
        ret_users.append(i[1]['ret_users'].sum())
        ratio.append(i[1]['ret_users'].sum() / i[1]['users'].sum())
    # 构建数据框
    y = pd.DataFrame({'interests_news': interests_news, 
                     'users': users,
                     'ret_users': ret_users,
                     'ratio': ratio})
    # 输出
    y.to_csv('大于5的用户数分组计算结果.csv', index = False, encoding='gbk')
    t1 = time.time()
    print('数据清洗完毕,所需时间为 %.2f s' % (t1-t0))
    return y.head()    
Cleandata()
(42934, 5)
(403, 5)
(934, 4)
数据清洗完毕,所需时间为 3.58 s
interests_newsusersret_usersratio
0CBA173.7070812561.473745
1NBA392.7998308842.250510
2三农87.064592911.045201
3世界史67.310528480.713113
4两性421.0346834050.961916

数据

上述代码所用到的数据

有兴趣的小伙伴可以自己尝试一波哦~

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值