练习题
Ex1:口袋妖怪数据集
现有一份口袋妖怪的数据集,下面进行一些背景说明:
#
代表全国图鉴编号,不同行存在相同数字则表示为该妖怪的不同状态
妖怪具有单属性和双属性两种,对于单属性的妖怪,Type 2
为缺失值
Total, HP, Attack, Defense, Sp. Atk, Sp. Def, Speed
分别代表种族值、体力、物攻、防御、特攻、特防、速度,其中种族值为后6项之和
- 对
HP, Attack, Defense, Sp. Atk, Sp. Def, Speed
进行加总,验证是否为Total
值。 - 对于
#
重复的妖怪只保留第一条记录,解决以下问题:
- 求第一属性的种类数量和前三多数量对应的种类
- 求第一属性和第二属性的组合种类
求尚未出现过的属性组合照下述要求,构造Series
:
- 取出物攻,超过120的替换为
high
,不足50的替换为low
,否则设为mid
- 取出第一属性,分别用
replace
和apply
替换所有字母为大写
求每个妖怪六项能力的离差,即所有能力中偏离中位数最大的值,添加到df
并从大到小排序
第一问:对HP, Attack, Defense, Sp. Atk, Sp. Def, Speed
进行加总,验证是否为Total
值。
df_demo = df[['HP','Attack', 'Defense','Sp. Atk','Sp. Def','Speed']]
(df_demo.sum(1)!=df['Total']).mean()
参考答案:
df = pd.read_csv('../data/pokemon.csv')
(df[['HP', 'Attack', 'Defense', 'Sp. Atk', 'Sp. Def', 'Speed']].sum(1)!=df['Total']).mean()
第二问:
- 对于
#
重复的妖怪只保留第一条记录,解决以下问题:
- 求第一属性的种类数量和前三多数量对应的种类
df_2=df.drop_duplicates('#', keep='first')
df_2['Type 1'].nunique()
df_2['Type 1'].value_counts().index[:3]
参考答案:
dp_dup = df.drop_duplicates('#', keep='first')
dp_dup['Type 1'].nunique()
dp_dup['Type 1'].value_counts().index[:3]
- 求第一属性和第二属性的组合种类
df_3=df.drop_duplicates(['Type 1','Type 2'])
df_3.shape[0]
第三问:
求尚未出现过的属性组合照下述要求,构造Series
:
- 取出物攻,超过120的替换为
high
,不足50的替换为low
,否则设为mid
df['Attack'].where(df['Attack']<=120, 'high').where(df['Attack']>=50, 'low').where((50>df['Attack'])&(df['Attack']>120), 'mid').head()
参考答案:
df['Attack'].mask(df['Attack']>120, 'high').mask(df['Attack']<50, 'low').mask((50<=df['Attack'])&(df['Attack']<=120), 'mid').head()
- 取出第一属性,分别用
replace
和apply
替换所有字母为大写
参考答案:
df['Type 1'].replace({i:str.upper(i) for i in df['Type 1'].unique()})
df['Type 1'].apply(lambda x:str.upper(x)).head()
第三问:求每个妖怪六项能力的离差,即所有能力中偏离中位数最大的值,添加到df
并从大到小排序
参考答案:
df['Deviation'] = df[['HP', 'Attack', 'Defense', 'Sp. Atk', 'Sp. Def', 'Speed']].apply(lambda x:np.max((x-x.median()).abs()), 1)
df.sort_values('Deviation', ascending=False).head()
Ex2:指数加权窗口
- 作为扩张窗口的
ewm
窗口
在扩张窗口中,用户可以使用各类函数进行历史的累计指标统计,但这些内置的统计函数往往把窗口中的所有元素赋予了同样的权重。事实上,可以给出不同的权重来赋给窗口中的元素,指数加权窗口就是这样一种特殊的扩张窗口。
其中,最重要的参数是alpha
,它决定了默认情况下的窗口权重为wi=(1−α)i,i∈{0,1,...,t}wi=(1−α)i,i∈{0,1,...,t},其中i=ti=t表示当前元素,i=0i=0表示序列的第一个元素。
从权重公式可以看出,离开当前值越远则权重越小,若记原序列为xx,更新后的当前元素为ytyt,此时通过加权公式归一化后可知:
对于Series
而言,可以用ewm
对象如下计算指数平滑后的序列:
请用expanding
窗口实现。
- 作为滑动窗口的
ewm
窗口
从第1问中可以看到,ewm
作为一种扩张窗口的特例,只能从序列的第一个元素开始加权。现在希望给定一个限制窗口n
,只对包含自身最近的n
个窗口进行滑动加权平滑。请根据滑窗函数,给出新的wi
与yt
的更新公式,并通过rolling
窗口实现这一功能。
这道题没想明白,现在也还是在思考中,故给出参考答案。
np.random.seed(0)
s = pd.Series(np.random.randint(-1,2,30).cumsum())
s.ewm(alpha=0.2).mean().head()
def ewm_func(x, alpha=0.2):
win = (1-alpha)**np.arange(x.shape[0])[::-1]
res = (win*x).sum()/win.sum()
return res
s.expanding().apply(ewm_func).head()
s.rolling(window=4).apply(ewm_func).head()
小结
看懂每一个知识点容易,但是把它运用在实际的场景时,就不知道怎么用了。就像我知道加减乘除,但是应用题还是做不来一样。请各位观众老爷们给上您宝贵的建议。
参考文献:
DataWhale Pandas数据分析;