DataWhale组队学习pandas task02(下:练习)
这次任务一共有两个题目:
Ex1:口袋妖怪数据集
现有一份口袋妖怪的数据集,下面进行一些背景说明:
-
#
代表全国图鉴编号,不同行存在相同数字则表示为该妖怪的不同状态 -
妖怪具有单属性和双属性两种,对于单属性的妖怪,
Type 2
为缺失值 -
Total, HP, Attack, Defense, Sp. Atk, Sp. Def, Speed
分别代表种族值、体力、物攻、防御、特攻、特防、速度,其中种族值为后6项之和
1、对 HP, Attack, Defense, Sp. Atk, Sp. Def, Speed
进行加总,验证是否为 Total
值。
-
import pandas as pd df = pd.read_csv('./data/pokemon.csv') df.head() # Name Type 1 Type 2 Total HP Attack Defense Sp. Atk Sp. Def Speed 0 1 Bulbasaur Grass Poison 318 45 49 49 65 65 45 1 2 Ivysaur Grass Poison 405 60 62 63 80 80 60 2 3 Venusaur Grass Poison 525 80 82 83 100 100 80 3 3 VenusaurMega Venusaur Grass Poison 625 80 100 123 122 120 80 4 4 Charmander Fire NaN 309 39 52 43 60 50 65 对 HP, Attack, Defense, Sp. Atk, Sp. Def, Speed 进行加总,验证是否为 Total 值。 对于 # 重复的妖怪只保留第一条记录,解决以下问题: 求第一属性的种类数量和前三多数量对应的种类 求第一属性和第二属性的组合种类 求尚未出现过的属性组合 按照下述要求,构造 Series : 取出物攻,超过120的替换为 high ,不足50的替换为 low ,否则设为 mid 取出第一属性,分别用 replace 和 apply 替换所有字母为大写 求每个妖怪六项能力的离差,即所有能力中偏离中位数最大的值,添加到 df 并从大到小排序 #1、对 HP, Attack, Defense, Sp. Atk, Sp. Def, Speed 进行加总,验证是否为 Total 值。 s = [(df['HP']+df['Attack']+df['Defense']+df['Sp. Atk']+df['Sp. Def']+df['Speed']).values == df['Total'].values][0] set(s) out:{True}
第一问的思路相对简单,就是把这几列的数相加然后判断和total的值是否相等,返回bool数组,再去重,发现得到Ture ,那么证明这些列的和就是total。
2、对于 #
重复的妖怪只保留第一条记录,解决以下问题:
a、求第一属性的种类数量和前三多数量对应的种类
b、求第一属性和第二属性的组合种类
c、求尚未出现过的属性组合
#对于 # 重复的妖怪只保留第一条记录,解决以下问题:
df.drop_duplicates(['#'],keep='first')
# Name Type 1 Type 2 Total HP Attack Defense Sp. Atk Sp. Def Speed
0 1 Bulbasaur Grass Poison 318 45 49 49 65 65 45
1 2 Ivysaur Grass Poison 405 60 62 63 80 80 60
2 3 Venusaur Grass Poison 525 80 82 83 100 100 80
4 4 Charmander Fire NaN 309 39 52 43 60 50 65
5 5 Charmeleon Fire NaN 405 58 64 58 80 65 80
... ... ... ... ... ... ... ... ... ... ... ...
793 717 Yveltal Dark Flying 680 126 131 95 131 98 99
794 718 Zygarde50% Forme Dragon Ground 600 108 100 121 81 95 95
795 719 Diancie Rock Fairy 600 50 100 150 100 150 50
797 720 HoopaHoopa Confined Psychic Ghost 600 80 110 60 150 130 70
799 721 Volcanion Fire Water 600 80 110 120 130 90 70
#求第一属性的种类数量和前三多数量对应的种类
df['Type 1'].nunique()
out:18
df['Type 1'].value_counts()[:3]
Water 112
Normal 98
Grass 70
Name: Type 1, dtype: int64
#求第一属性和第二属性的组合种类
len(df.dropna().drop_duplicates(['Type 1','Type 2']))
out:136
#求尚未出现过的属性组合
dta = df.dropna().drop_duplicates(['Type 1','Type 2'])
tpye = df[ df['Type 2'].isna()]['Type 1'].unique()#type1 种类
#已有组合
type1_2 = list(zip(dta['Type 1'],dta['Type 2']))
type1_2.append( list(zip(dta['Type 2'],dta['Type 1'])))
import itertools
com = list(itertools.permutations(tpye, 2))
list(set(list(com[0]))^set(list(type1_2[1])))
emt = []
for i in com:
if i not in type1_2:
emt.append(i)
ned_ls = []
for i in emt:
for j in emt:
if list(set(list(i))^set(list(j))) != []:
ned_ls.append(i)
list(set(ned_ls))
本题重点在第三个问,求出为出现的组合,我这里将单属性的抽出来去重,使用itertools.permutations来进行两两组合,然后将Type1和type2进行zip,注意,这里为了防止原数据中的组合顺序问题(a,b)(b,a)的情况,我这里将type1和type2交换顺序额进行了组合,然后for循环遍历原组合和新组合列表,找出新的组合,找出新组合后再对新的组合进行顺序去重保证不会出现(a,b)(b,a)同时出现的情况。
3、按照下述要求,构造 Series
:
-
取出物攻,超过120的替换为
high
,不足50的替换为low
,否则设为mid
-
取出第一属性,分别用
replace
和apply
替换所有字母为大写 -
求每个妖怪六项能力的离差,即所有能力中偏离中位数最大的值,添加到
df
并从大到小排序
dat_att = df['Attack']
def re(x):
if x > 120:
x = 'high'
elif x<50:
x = ' low'
else:
x = 'mid'
return x
dat_att.apply(re)
0 low
1 mid
2 mid
3 mid
4 mid
...
795 mid
796 high
797 mid
798 high
799 mid
Name: Attack, Length: 800, dtype: object
#取出第一属性,分别用 replace 和 apply 替换所有字母为大写
typ1 = df['Type 1'].apply(lambda x : x.upper())
df['Type 1'].replace(df['Type 1'].values,(df['Type 1'].str.upper().values))
0 GRASS
1 GRASS
2 GRASS
3 GRASS
4 FIRE
...
795 ROCK
796 ROCK
797 PSYCHIC
798 PSYCHIC
799 FIRE
Name: Type 1, Length: 800, dtype: object
#求每个妖怪六项能力的离差,即所有能力中偏离中位数最大的值,添加到 df 并从大到小排序
ds = df.loc[:,'HP':]
ds.apply(lambda x:(x-x.median()).abs().max()).sort_values(ascending = False)
感觉这个文就是灵活应用函数映射,要对pandas的各种函数功能熟悉。
Ex2:指数加权窗口
-
作为扩张窗口的
ewm
窗口
在扩张窗口中,用户可以使用各类函数进行历史的累计指标统计,但这些内置的统计函数往往把窗口中的所有元素赋予了同样的权重。事实上,可以给出不同的权重来赋给窗口中的元素,指数加权窗口就是这样一种特殊的扩张窗口。
其中,最重要的参数是 alpha
,它决定了默认情况下的窗口权重为 wi=(1−α)i,i∈{0,1,...,t}wi=(1−α)i,i∈{0,1,...,t} ,其中 i=ti=t 表示当前元素, i=0i=0 表示序列的第一个元素。
从权重公式可以看出,离开当前值越远则权重越小,若记原序列为 x
,更新后的当前元素为 ytyt ,此时通过加权公式归一化后可知:
对于 Series
而言,可以用 ewm
对象如下计算指数平滑后的序列:
def ewm_alpha(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()
这题思路其实就是将加权归一化的公式表达出来。
2.作为滑动窗口的 ewm
窗口
从第1问中可以看到, ewm
作为一种扩张窗口的特例,只能从序列的第一个元素开始加权。现在希望给定一个限制窗口 n
,只对包含自身的最近的 n
个元素作为窗口进行滑动加权平滑。请根据滑窗函数,给出新的 wiwi 与 ytyt 的更新公式,并通过 rolling
窗口实现这一功能。
s.rolling(window=2).apply(ewm_alpha).head()
这题两问总结一下其实就是一个问题,就是定义加权公式归一华后的公式,这里要熟练使用numpy。