Table of Contents
- 1 問題背景
- 2 總結遇到的坑
- 3 導入相應的庫+定義函數
- 4 處理流程
- 4.1 讀入資料
- 4.2 篩選資料
- 4.3 字元串處理
- 4.4 對興趣點變量進行拆分
- 4.5 分組計算
- 5 封裝成函數
問題背景
最近在某網際網路公司實習,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)
day | interests_news | users | ret_users | 次留 | |
---|---|---|---|---|---|
1 | 20190311 | ["娛樂/明星八卦"] | 363.829957 | 2087 | 0.521120 |
2 | 20190311 | ["健康/養生"] | 27.469583 | 602 | 0.398086 |
3 | 20190311 | ["娛樂/明星八卦","娛樂"] | 411.894976 | 475 | 0.025857 |
4 | 20190311 | ["體育/NBA"] | 47.831449 | 432 | 0.058352 |
5 | 20190311 | ["社會"] | 183.316248 | 401 | 0.103651 |
篩選資料
data_10 = data[data['users'] > 5]
# 重新設定索引
data_10 = data_10.reset_index(drop=True)
print(data_10.shape)
data_10.head()
(403, 5)
day | interests_news | users | ret_users | 次留 | |
---|---|---|---|---|---|
20190311 | ["娛樂/明星八卦"] | 363.829957 | 2087 | 0.521120 | |
1 | 20190311 | ["健康/養生"] | 27.469583 | 602 | 0.398086 |
2 | 20190311 | ["娛樂/明星八卦","娛樂"] | 411.894976 | 475 | 0.025857 |
3 | 20190311 | ["體育/NBA"] | 47.831449 | 432 | 0.058352 |
4 | 20190311 | ["社會"] | 183.316248 | 401 | 0.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)
day | interests_news | users | ret_users | 次留 | |
---|---|---|---|---|---|
20190311 | 明星八卦 | 363.829957 | 2087 | 0.521120 | |
1 | 20190311 | 養生 | 27.469583 | 602 | 0.398086 |
2 | 20190311 | 明星八卦, 娛樂 | 411.894976 | 475 | 0.025857 |
3 | 20190311 | NBA | 47.831449 | 432 | 0.058352 |
4 | 20190311 | 社會 | 183.316248 | 401 | 0.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_news | users | ret_users | 次留 | |
---|---|---|---|---|
明星八卦 | 363.829957 | 2087 | 0.521120 | |
養生 | 27.469583 | 602 | 0.398086 | |
明星八卦 | 411.894976 | 475 | 0.025857 | |
1 | 娛樂 | 411.894976 | 475 | 0.025857 |
NBA | 47.831449 | 432 | 0.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_news | users | ret_users | ratio | |
---|---|---|---|---|
CBA | 173.707081 | 256 | 1.473745 | |
1 | NBA | 392.799830 | 884 | 2.250510 |
2 | 三農 | 87.064592 | 91 | 1.045201 |
3 | 世界史 | 67.310528 | 48 | 0.713113 |
4 | 兩性 | 421.034683 | 405 | 0.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()
(42934, 5)
(403, 5)
(934, 4)
資料清洗完畢,所需時間為 3.58 s
interests_news | users | ret_users | ratio | |
---|---|---|---|---|
CBA | 173.707081 | 256 | 1.473745 | |
1 | NBA | 392.799830 | 884 | 2.250510 |
2 | 三農 | 87.064592 | 91 | 1.045201 |
3 | 世界史 | 67.310528 | 48 | 0.713113 |
4 | 兩性 | 421.034683 | 405 | 0.961916 |
資料
上述代碼所用到的資料
有興趣的小夥伴可以自己嘗試一波哦~