問題1 計算漲幅
- 題目描述
一個 df 有三個列需要進行計算,change_type 值 為1和0, 1為漲價,0為降價, price為現(xiàn)價, changed為漲降價的絕對值, 現(xiàn)求:漲降價的比例, 精確到0位,無小數(shù)位。 - 知識點提要
(1)apply + lambda函數(shù)
(2)map + format
(3)區(qū)分apply和map
傳送門:pandas常用知識點 - 解法
#1.構(gòu)造數(shù)據(jù)
import pandas as pd
df = pd.DataFrame({'change_type' : [1,1,0,0,1,0],
'price' : [100, 90, 50, 120, 150, 200],
'changed' : [10,8,4,11,14,10]})
#通過字典創(chuàng)建dataframe
#2.編寫函數(shù)
#第一個函數(shù)計算漲幅
#第二個函數(shù)轉(zhuǎn)換為要求格式的百分比
func1 = lambda x: x['changed']/x['price'] if x['change_type'] == 1 else -x['changed']/x['price']
#注意1,結(jié)合apply時候設(shè)置axis=1參數(shù),否則報錯。
#注意2,pandas結(jié)合lambda函數(shù)可以針對整個df進行操作。
func2 = lambda x: format(x,'.0%')
#注意格式處理的方法,有兩種一種是%占位符,一種是format,個人認為現(xiàn)用現(xiàn)百度。
#3.計算
df['percentage'] = df.apply(func1,axis=1).map(lambda x:format(x,'.0%'))
問題2 同一個dataframe里根據(jù)某列值更改另一列的值
- 題目描述
有一個dataframe存儲了兩列數(shù)據(jù),一列點評ID,一列點評狀態(tài),要求點評ID為null的點評狀態(tài)賦值為0,點評ID不為null的賦值為1。 - 知識點提要
(1)apply+自定義函數(shù)(def)
(2)loc + 數(shù)據(jù)框賦值 + ~用法 - 解法
#1.構(gòu)造數(shù)據(jù)
df = pd.DataFrame(
{"has_comment_or_not":['0','0','0','1','0','0'],
"comment_status":["null","null","120047007","null","null","122121"]}
)
#2.解法1:編寫函數(shù)求解
##2.1 編寫傳統(tǒng)函數(shù)
def change_status(s):
if s.comment_status == 'null':
return 0
else:
return 1
#這種做法更適合復(fù)雜的業(yè)務(wù)場景,用編寫函數(shù)的形式做一套流程化的東西,s就可以認為是數(shù)據(jù)框,再apply的時候設(shè)置axis=1。
##2.2應(yīng)用函數(shù)
df['has_comment_or_not'] = df5.apply(change_status,axis=1)
#3.解法2:loc求解
##篩選條件,分等和不等兩種
df.loc[df['comment_status'] == 'null','has_comment_or_not'] = 0
df.loc[~(df['comment_status'] == 'null'),'has_comment_or_not'] = 1
問題3 用另一個dataframe的值替換當前dataframe的值
- 題目描述:
有一個df1,里邊存儲著英文的蔬菜名,有另外一個df2,里邊存儲著蔬菜名和對應(yīng)的大類別,要求按照df2的蔬菜名和大類別對應(yīng)關(guān)系給df1的蔬菜名重新賦值。
注意:如果df2中沒有df1中的蔬菜名那么蔬菜1保留原值;
如果df2中對應(yīng)的大類別為空,那么df1中的蔬菜名保持原值;
其他情況進行替換。 - 知識點提要
(1)map+字典
(2)map+dataframe - 解法
#1.構(gòu)造數(shù)據(jù)
df1 = pd.DataFrame({'ItemType1':['redTomato',
'whitePotato',
'yellowPotato',
'greenCauliflower',
'yellowCauliflower',
'yelloSquash',
'redOnions',
'YellowOnions',
'WhiteOnions',
'yellowCabbage',
'GreenCabbage']})
df2 = pd.DataFrame({'ItemType2':['whitePotato',
'yellowPotato',
'redTomato',
'yellowCabbage',
'GreenCabbage',
'yellowCauliflower',
'greenCauliflower',
'YellowOnions',
'WhiteOnions',
'yelloSquash',
'redOnions'],
'newType':['Potato',
'Potato',
'Tomato',
'',
'',
'yellowCauliflower',
'greenCauliflower',
'Onions',
'Onions',
'Squash',
'Onions']})
#2.思路1:用“map+字典”解決
#首先需要將df2的兩列轉(zhuǎn)換為字典,直接轉(zhuǎn)肯定是沒有函數(shù)了,
#首先添加一個輔助列,把二者對應(yīng)為字典,
#然后根據(jù)字典的特征,構(gòu)造一個大字典。
#然后map掉。
df2['map_1'] = df2.apply(lambda x: {x['ItemType2']:x['newType']} if x['newType'] else {x['ItemType2']:x['ItemType2']},axis=1)
new_dict = {}
for dict1 in df2['map_1'].tolist():
for k,v in dict1.items():
if k not in new_dict:
new_dict[k] = v
else:
new_dict[k].append(v)
df1['ItemType1'] = df1['ItemType1'].map(new_dict)
#3.思路2:map + df用法
#這個思路和上面的類似,只不過map可以和df結(jié)合使用,這里的df要設(shè)置index,相當于key
#首先需要把空格替換為原值
df2 = df2.set_index('ItemType2')
df2.loc[df2['newType'] == '','newType'] = df2.loc[df2['newType'] == ''].index
df1['ItemType1'] = df1['ItemType1'].map(df2.newType)
問題4 銷售數(shù)據(jù)的聚合統(tǒng)計
題目描述:
有一個tsv文件存儲著某公司的銷售數(shù)據(jù),讀入這個tsv,并對數(shù)據(jù)做以下統(tǒng)計:
(1)統(tǒng)計下單最多的商品(item_name)
(2)統(tǒng)計有多少種商品被下單
(3)統(tǒng)計下單最多的商品(choice_description)
(4)計算所有商品的總收入
(5)統(tǒng)計訂單數(shù)
(6)統(tǒng)計所有訂單的平均收入知識點提要
(1)groupby + apply/map
(2)nunique
(3)sort_values
(4)astype解法
df6 = pd.read_csv(r'C:/Users/wangxiaowei11772/Desktop/exercise_data/chipotle.tsv',sep='\t')
#下單最多的商品(item_name)
df6.groupby('item_name').quantity.apply(sum).sort_values(ascending=False).index[0]
#統(tǒng)計有多少種商品被下單
df6[df6['quantity'] > 0].item_name.nunique()
#下單最多的商品(choice_description)
df6[['choice_description','quantity']].dropna().groupby('choice_description').agg({'quantity':sum}).sort_values(by= 'quantity', ascending = False).head(1).index
#將item_price轉(zhuǎn)換為浮點數(shù)
df6['item_price'] = df6.item_price.apply(lambda x: x[1:]).map(float)
#計算商品的總收入
df6['sum_revenue'] = df6['quantity']*df6['item_price'].astype(float)
df6['sum_revenue'].sum()
#直接寫sum有問題是對每一個元素求sum相當于沒求,所以還是先增列再求和比較穩(wěn)妥
#統(tǒng)計訂單數(shù)
df6.order_id.nunique()
#統(tǒng)計所有訂單的平均收入
round(df6.groupby('order_id').sum_revenue.sum().mean(),2)
問題5 統(tǒng)計每位學(xué)生平均分數(shù)最高的課程
- 題目描述
有一個數(shù)據(jù)框存儲著學(xué)生的考試成績,但考試成績分為期中和期末兩次,計算每一個同學(xué)的平均分。 - 知識點提要
(1)reset_index()
(2)idxmax和iloc的使用 - 解法
#1.創(chuàng)建數(shù)據(jù)框
dict1 = {'ID': [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],
'cls': ['math', 'math', 'en', 'en', 'math', 'math', 'en', 'en', 'math', 'math', 'en', 'en'],
'score': [95, 98, 86, 85, 67, 87, 89, 97, 87, 86, 89, 87]}
df6 = pd.DataFrame(dict1)
#2.計算平均分數(shù)
df7 = df6.groupby(['ID','cls']).score.mean().reset_index()
#3.找出最高分數(shù)的課程
df7.iloc[df7.groupby(['ID']).score.idxmax(),1:3]
問題6 數(shù)據(jù)框的轉(zhuǎn)置
- 題目
這個問題是一道休閑題,算是這個系列到這的一個休息。問題有一個數(shù)據(jù)框,如何實現(xiàn)行和列的轉(zhuǎn)置。 - 知識點提要
(1).T
(2)stack和unstack - 解法
#1.構(gòu)造數(shù)據(jù)
import pandas as pd
import numpy as np
tmp = np.arange(16).reshape(4,4)
columns = ['a','b','c','d']
indexs = ['aa','bb','cc','dd']
df1 = pd.DataFrame(tmp,columns=columns,index=indexs)
#2.解法
#2.1 最簡單解法
df1.T
#dataframe也可以用轉(zhuǎn)置這個很神奇
#2.2 stack解法
df2 = df1.stack()
df2 = df2.unstack(level=0)
#stack和unstack有個參數(shù)level主要是控制index的層次
問題7 缺失值的處理
- 題目
現(xiàn)在有一個數(shù)據(jù)框,里邊由于數(shù)據(jù)存儲操作問題,存在很多缺失值,要如何處理這些缺失值。缺失值處理包括的內(nèi)容比較多,比如缺失值的統(tǒng)計,缺失值的刪除,缺失值的填充等等。具體題目包括:
(1)統(tǒng)計具有缺失值的列
(2)統(tǒng)計每一列有幾個缺失值
(3)刪除city列為空的數(shù)據(jù)
(4)處理age列的缺失值 - 知識點提要
(1)isna()
(2)any()
(3)fillna() - 解法
#構(gòu)造數(shù)據(jù)
import pandas as pd
import numpy as np
index = pd.Index(data=["Tom", "Bob", "Mary", "James", "Andy", "Alice"], name="name")
data = {
"age": [18, 30, np.nan, 40, np.nan, 30],
"city": ["BeiJing", "ShangHai", "GuangZhou", "ShenZhen", np.nan, " "],
"sex": [None, "male", "female", "male", np.nan, "unknown"],
"birth": ["2000-02-10", "1988-10-17", None, "1978-08-08", np.nan, "1988-10-17"]
}
df7 = pd.DataFrame(data, index=index)
#1.統(tǒng)計有缺失值的列
df7.isna().any()
#2.統(tǒng)計每一列有幾個缺失值
df7.isna().sum()
#3.刪除city列為空的數(shù)據(jù)
df7.dropna(subset=['city'],how='any')
#4.數(shù)據(jù)變量缺失值的填充
df7['age'].fillna(df7['age'].mean(),inplace=True)
##這里需要注意的是如果是mode可能有很多個數(shù),用個切片[0],把數(shù)據(jù)取出來
問題8 數(shù)據(jù)抽樣
等我補充
問題9 計算文本的平均長度
- 題目
現(xiàn)在有一個數(shù)據(jù)框,存的數(shù)據(jù)包括id和text兩列,現(xiàn)在要求平均文本你長度。 - 知識點提要
(1)lambda
(2)mean - 解法
#1.構(gòu)造數(shù)據(jù)
dict1 = {'Id':list(range(5)),
'text':['ab','a','abcd','abcde','aa']}
df1 = pd.DataFrame(dict1)
#2.求平均值
df1.text.apply(lambda x: len(x)).mean()
問題10 篩選出具有5個以上不同數(shù)據(jù)的所有數(shù)據(jù)
- 題目
現(xiàn)在有一個數(shù)據(jù)框,包括姓名和number兩列數(shù)據(jù),現(xiàn)在要求篩選出來具有五個以上number值的所有數(shù)據(jù),注意篩選出來的數(shù)據(jù)要包括姓名和number的所有數(shù)據(jù)。 - 知識點提要
(1)set_index
(2)dataframe切片 - 解法
#1.構(gòu)造數(shù)據(jù)
import numpy as np
import pandas as pd
import random
name_list = np.array([['王大偉']*7,['聶小萌']*6,['肖大潔']*5,['徐小花']*3])
name_list = [y for x in name_list.flatten() for y in x]
random.shuffle(name_list)
number = list(range(10000,10021))
random.shuffle(number)
dict1 = {'name':name_list,'number':number}
df1 = pd.DataFrame(dict1)
#2.求出滿足條件的數(shù)據(jù)
df1 = df1.set_index('name')
df2 = df1.groupby('name').count()
df1.loc[df2[df2.number>=5].index.tolist(),:]