pandas-第二章 索引

import numpy as np
import pandas as pd
df = pd.read_csv(r'D:\study\pandas\data\table.csv',index_col='ID')
df.head()
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1101S_1C_1Mstreet_11736334.0A+
1102S_1C_1Fstreet_21927332.5B+
1103S_1C_1Mstreet_21868287.2B+
1104S_1C_1Fstreet_21678180.4B-
1105S_1C_1Fstreet_41596484.8B+

一、单级索引

#1.loc方法、iloc方法、[]操作符
  #ilocs为位置索引,loc表示标签索引
#(a)loc方法(注意:所有在loc中使用的切片全部包含右端点)
# 本质上loc中能传入的只有不二列表和索引子集构成的列表
  #①单行索引
df.loc[1103]
School          S_1
Class           C_1
Gender            M
Address    street_2
Height          186
Weight           82
Math           87.2
Physics          B+
Name: 1103, dtype: object
#②多行索引
df.loc[[1102,2304]]
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1102S_1C_1Fstreet_21927332.5B+
2304S_2C_3Fstreet_61648195.5A-
df.loc[1304:].head()
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1304S_1C_3Mstreet_21957085.2A
1305S_1C_3Fstreet_51876961.7B-
2101S_2C_1Mstreet_71748483.3C
2102S_2C_1Fstreet_61616150.6B+
2103S_2C_1Mstreet_41576152.5B-
df.loc[2402::-1].head()
SchoolClassGenderAddressHeightWeightMathPhysics
ID
2402S_2C_4Mstreet_71668248.7B
2401S_2C_4Fstreet_21926245.3A
2305S_2C_3Mstreet_41877348.9B
2304S_2C_3Fstreet_61648195.5A-
2303S_2C_3Fstreet_71909965.9C
#③单列索引
df.loc[:,'Height'].head()
ID
1101    173
1102    192
1103    186
1104    167
1105    159
Name: Height, dtype: int64
#④多列索引
df.loc[:,['Height','Math']].head()
HeightMath
ID
110117334.0
110219232.5
110318687.2
110416780.4
110515984.8
df.loc[:,'Height':'Math'].head()
HeightWeightMath
ID
11011736334.0
11021927332.5
11031868287.2
11041678180.4
11051596484.8
#⑤联合索引
df.loc[1102:2401:3,'Height':'Math'].head() #1102-2401,每隔3个
HeightWeightMath
ID
11021927332.5
11051596484.8
12031605358.8
13011616831.5
13041957085.2
#⑥函数式索引
df.loc[lambda x:x['Gender']=='M'].head() 
#‘Gender'值为M的行
#Loc中使用的函数,传入参数就是前面的df
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1101S_1C_1Mstreet_11736334.0A+
1103S_1C_1Mstreet_21868287.2B+
1201S_1C_2Mstreet_51886897.0A-
1203S_1C_2Mstreet_61605358.8A+
1301S_1C_3Mstreet_41616831.5B+
def f(x):
    return [1101,1103]
df.loc[f]
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1101S_1C_1Mstreet_11736334.0A+
1103S_1C_1Mstreet_21868287.2B+
#⑦布尔索引
df.loc[df['Address'].isin(['street_7','street_4'])].head()

#isin接受一个列表,判断'Address'的值是否在该List内
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1105S_1C_1Fstreet_41596484.8B+
1202S_1C_2Fstreet_41769463.5B-
1301S_1C_3Mstreet_41616831.5B+
1303S_1C_3Mstreet_71888249.7B
2101S_2C_1Mstreet_71748483.3C
df.loc[[True if i[-1]=='4' or i[-1]=='7' else False for i in df['Address'].values]].head()
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1105S_1C_1Fstreet_41596484.8B+
1202S_1C_2Fstreet_41769463.5B-
1301S_1C_3Mstreet_41616831.5B+
1303S_1C_3Mstreet_71888249.7B
2101S_2C_1Mstreet_71748483.3C
#(b)iloc方法(注意:与Loc不同,切片右端点不包含)
# iloc中接受的参数只能为整数或整数列表,不能使用布尔索引
   #①单行索引
df.iloc[3]
School          S_1
Class           C_1
Gender            F
Address    street_2
Height          167
Weight           81
Math           80.4
Physics          B-
Name: 1104, dtype: object
#②多行索引
df.iloc[3:5]
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1104S_1C_1Fstreet_21678180.4B-
1105S_1C_1Fstreet_41596484.8B+
#③单列索引
df.iloc[:,3].head()
ID
1101    street_1
1102    street_2
1103    street_2
1104    street_2
1105    street_4
Name: Address, dtype: object
#④多列索引
df.iloc[:,7::-2].head() #第八列开始每倒数两列
PhysicsWeightAddressClass
ID
1101A+63street_1C_1
1102B+73street_2C_1
1103B+82street_2C_1
1104B-81street_2C_1
1105B+64street_4C_1
#⑤混合索引
df.iloc[3::4,7::-2].head()
#第三行开始每隔四行,第8列开始每倒数2列
PhysicsWeightAddressClass
ID
1104B-81street_2C_1
1203A+53street_6C_2
1302A-57street_1C_3
2101C84street_7C_1
2105A81street_4C_1
#⑥函数式索引
df.iloc[lambda x:[3]].head()
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1104S_1C_1Fstreet_21678180.4B-
#(c)[]操作符
 #Attention:不要再行索引为浮点时使用[]操作符;
    #因为再Series中浮点[]并不是进行位置比较,而是值比较,非常特殊

#一般来说,[]操作符常用于列选择或不二选择,尽量避免行的选择

# (c.1) Series的[]操作
#①单元素索引
s = pd.Series(df['Math'],index=df.index)
s[1101] #使用的时索引标签
34.0
#②多行索引
s[0:4]  #使用的是绝对位置的整数切片,与元素无关,注意
ID
1101    34.0
1102    32.5
1103    87.2
1104    80.4
Name: Math, dtype: float64
#③函数式索引
s[lambda x: x.index[16::-6]]
#注意使用lambda函数时,直接切片会报错,此时使用的不是绝对位置切片,而是元素切片
ID
2102    50.6
1301    31.5
1105    84.8
Name: Math, dtype: float64
#④布尔索引
s[s>80]
ID
1103    87.2
1104    80.4
1105    84.8
1201    97.0
1302    87.7
1304    85.2
2101    83.3
2205    85.4
2304    95.5
Name: Math, dtype: float64
# (c.2) DataFrame的[]操作
#①单元素索引
df[1:2]
# 注意不要携程df['label'],会报错
# 同Series使用了绝对位置切片
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1102S_1C_1Fstreet_21927332.5B+
#???没看懂
#如果想要获得某一个元素,可以使用get_loc方法 
row = df.index.get_loc(1102)
df[row:row+1]
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1102S_1C_1Fstreet_21927332.5B+
#②多行索引
#用切片,如果始选取指定的某几行,推荐使用Loc,否则很可能报错
df[3:5] #df.iloc[3:5]
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1104S_1C_1Fstreet_21678180.4B-
1105S_1C_1Fstreet_41596484.8B+
#③单列索引
df['School'].head()
ID
1101    S_1
1102    S_1
1103    S_1
1104    S_1
1105    S_1
Name: School, dtype: object
#④多列索引
df[['School','Math']].head()
SchoolMath
ID
1101S_134.0
1102S_132.5
1103S_187.2
1104S_180.4
1105S_184.8
# ⑤函数式索引
df[lambda x:['Math','Physics']].head()
MathPhysics
ID
110134.0A+
110232.5B+
110387.2B+
110480.4B-
110584.8B+
#⑥布尔索引
df[df['Gender']=='F'].head()
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1102S_1C_1Fstreet_21927332.5B+
1104S_1C_1Fstreet_21678180.4B-
1105S_1C_1Fstreet_41596484.8B+
1202S_1C_2Fstreet_41769463.5B-
1204S_1C_2Fstreet_51626333.8B
#2.布尔索引
#(a)布尔符号:and&  or|  not~
df[(df['Gender']=='F')&(df['Address']=='street_2')].head()
# Gender=F and Adress='street_2'的所有值
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1102S_1C_1Fstreet_21927332.5B+
1104S_1C_1Fstreet_21678180.4B-
2401S_2C_4Fstreet_21926245.3A
2404S_2C_4Fstreet_21608467.7B
df[(df['Math']>85)|(df['Address']=='street_7')].head()
# Math>85 or Address=street_7
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1103S_1C_1Mstreet_21868287.2B+
1201S_1C_2Mstreet_51886897.0A-
1302S_1C_3Fstreet_11755787.7A-
1303S_1C_3Mstreet_71888249.7B
1304S_1C_3Mstreet_21957085.2A
df[~((df['Math']>75)|(df['Address']=='street_1'))].head()
#not(math>75 or address=street1) 即math<75 and address !+street_1
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1102S_1C_1Fstreet_21927332.5B+
1202S_1C_2Fstreet_41769463.5B-
1203S_1C_2Mstreet_61605358.8A+
1204S_1C_2Fstreet_51626333.8B
1205S_1C_2Fstreet_61676368.4B-
#???没看懂
#loc和[]中相应位置都能使用布尔列表选择
df.loc[df['Math']>60,(df[:8]['Address']=='street_6').values].head()
Physics
ID
1103B+
1104B-
1105B+
1201A-
1202B-
#(b)isin方法

# Address值为1或4 且 physics 为A A+
df[df['Address'].isin(['street_1','street_4'])
   &df['Physics'].isin(['A','A+'])]
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1101S_1C_1Mstreet_11736334.0A+
2105S_2C_1Mstreet_41708134.2A
2203S_2C_2Mstreet_41559173.8A+
#也可以用字典方式写:
df[df[['Address','Physics']].isin(
    {'Address':['street_1','street_4'],'Physics':['A','A+']}).all(1)]
#all 与&思路类似,1代表按照跨列方向判断是否全为True
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1101S_1C_1Mstreet_11736334.0A+
2105S_2C_1Mstreet_41708134.2A
2203S_2C_2Mstreet_41559173.8A+
#3.快速标量索引
display(df.at[1101,'School'])
display(df.loc[1101,'School'])
display(df.iat[0,0])
display(df.iloc[0,0])

%timeit df.at[1101,'School']
%timeit df.loc[1101,'School']
%timeit df.iat[0,0]
%timeit df.iloc[0,0]
#对比时间可发现,当只需取一个元素时,at和iat方法能够提供更快的实现
'S_1'



'S_1'



'S_1'



'S_1'


5.62 µs ± 501 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
11 µs ± 1.21 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)
6.85 µs ± 503 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
12.5 µs ± 1.91 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)
#4.区间索引  
#(a) 利用Interval_range方法
pd.interval_range(start=0,end=5)
 #closed参数可选'left','right','both','neither',默认左开右闭
IntervalIndex([(0, 1], (1, 2], (2, 3], (3, 4], (4, 5]],
              closed='right',
              dtype='interval[int64]')
pd.interval_range(start=0,periods=8,freq=5)
#periods参数控制区间个数,freq控制步长
IntervalIndex([(0, 5], (5, 10], (10, 15], (15, 20], (20, 25], (25, 30], (30, 35], (35, 40]],
              closed='right',
              dtype='interval[int64]')
#(b) 利用cut将数值列转为区间为元素的分类变量,例如统计数学成绩的区间情况:
math_interval=pd.cut(df['Math'],bins=[0,40,60,80,100])
#注意,如果没有类型转换,此时并不是区间类型,而是category类型
math_interval.head()
ID
1101      (0, 40]
1102      (0, 40]
1103    (80, 100]
1104    (80, 100]
1105    (80, 100]
Name: Math, dtype: category
Categories (4, interval[int64]): [(0, 40] < (40, 60] < (60, 80] < (80, 100]]
#???没看懂
#(c) 区间索引的选取
df_i = df.join(math_interval,rsuffix='_interval')[['Math','Math_interval']]\
            .reset_index().set_index('Math_interval')
df_i.head()
IDMath
Math_interval
(0, 40]110134.0
(0, 40]110232.5
(80, 100]110387.2
(80, 100]110480.4
(80, 100]110584.8
df_i.loc[65].head()
#包含该值就会被选中
IDMath
Math_interval
(60, 80]120263.5
(60, 80]120568.4
(60, 80]130561.7
(60, 80]210472.2
(60, 80]220268.5
df_i.loc[[65,90]].head()
IDMath
Math_interval
(60, 80]120263.5
(60, 80]120568.4
(60, 80]130561.7
(60, 80]210472.2
(60, 80]220268.5
# 如果想要选取某个区间,先要把分类变量转换为区间变量,再使用overlap方法
#df_i.loc[pd.Interval(70,75)].head()会报错
df_i[df_i.index.astype('interval').overlaps(pd.Interval(70,85))].head()
IDMath
Math_interval
(80, 100]110387.2
(80, 100]110480.4
(80, 100]110584.8
(80, 100]120197.0
(60, 80]120263.5

二、多级索引

# 1.创建多级索引
#(a)通过from_tuple或from_arrays
#①直接创建元组
tuples = [('A','a'),('A','b'),('B','a'),('B','b')]
mul_index = pd.MultiIndex.from_tuples(tuples,names=('Upper','Lower'))
mul_index
MultiIndex([('A', 'a'),
            ('A', 'b'),
            ('B', 'a'),
            ('B', 'b')],
           names=['Upper', 'Lower'])
pd.DataFrame({'score':['perfect','good','fair','bad']},index=mul_index)
score
UpperLower
Aaperfect
bgood
Bafair
bbad
#②利用zip创建元组
L1 = list('AABB')
L2 = list('abab')
tuples = list(zip(L1,L2))
mul_index = pd.MultiIndex.from_tuples(tuples,names=('Upper','Lower'))
pd.DataFrame({'Score':['perfect','good','fair','bad']},index=mul_index)
Score
UpperLower
Aaperfect
bgood
Bafair
bbad
#③通过Array创建
arrays = [['A','a'],['A','b'],['B','a'],['B','b']]
mul_index = pd.MultiIndex.from_tuples(arrays,names=('Upper','Lower'))
pd.DataFrame({'Score':['perfect','good','fair','bad']},index=mul_index)
Score
UpperLower
Aaperfect
bgood
Bafair
bbad
mul_index #由此可看出内部自动转成元组
MultiIndex([('A', 'a'),
            ('A', 'b'),
            ('B', 'a'),
            ('B', 'b')],
           names=['Upper', 'Lower'])
# (b) 通过from_prodcut
L1 = ['A','B']
L2 = ['a','b']
pd.MultiIndex.from_product([L1,L2],names=('Upper','Lower'))
#两两相乘
MultiIndex([('A', 'a'),
            ('A', 'b'),
            ('B', 'a'),
            ('B', 'b')],
           names=['Upper', 'Lower'])
# (c) 指定df中的列创建(set_index方法)
df_using_mul = df.set_index(['Class','Address'])
df_using_mul.head()
SchoolGenderHeightWeightMathPhysics
ClassAddress
C_1street_1S_1M1736334.0A+
street_2S_1F1927332.5B+
street_2S_1M1868287.2B+
street_2S_1F1678180.4B-
street_4S_1F1596484.8B+
#2.多层索引切片
df_using_mul.head()
SchoolGenderHeightWeightMathPhysics
ClassAddress
C_1street_1S_1M1736334.0A+
street_2S_1F1927332.5B+
street_2S_1M1868287.2B+
street_2S_1F1678180.4B-
street_4S_1F1596484.8B+
#(a)一般切片
df_using_mul.sort_index().loc['C_2','street_5']
#df_using_mul.loc['C_2','street_5'] 
#当索引不排序时,单个索引会报出性能警告
#df_using_mul.index.is_lexsorted()
# False; 该函数检查是否排序
#df_using_mul.sort_index().index.is_lexsorted()
# True
SchoolGenderHeightWeightMathPhysics
ClassAddress
C_2street_5S_1M1886897.0A-
street_5S_1F1626333.8B
street_5S_2M19310039.1B
#???没太理解
df_using_mul.sort_index().loc[('C_2','street_6'):('C_3','street_4')]
# 注意此处由于使用了Loc,因此仍包括右端点
# df_using_mul.loc['C_2','street_5'):] 
#报错;当不排序时,不能使用多层切片

SchoolGenderHeightWeightMathPhysics
ClassAddress
C_2street_6S_1M1605358.8A+
street_6S_1F1676368.4B-
street_7S_2F1947768.5B+
street_7S_2F1837685.4B
C_3street_1S_1F1755787.7A-
street_2S_1M1957085.2A
street_4S_1M1616831.5B+
street_4S_2F1577872.3B+
street_4S_2M1877348.9B
df_using_mul.sort_index().loc[('C_2','street_7'):'C_3'].head()
#非元组也是合法的,表示选中该层的所有元素
SchoolGenderHeightWeightMathPhysics
ClassAddress
C_2street_7S_2F1947768.5B+
street_7S_2F1837685.4B
C_3street_1S_1F1755787.7A-
street_2S_1M1957085.2A
street_4S_1M1616831.5B+
#(b)第一类特殊情况:由元组构成列表
df_using_mul.sort_index().loc[[('C_2','street_7'),('C_3','street_2')]]
#表示选出某几个元素,精确到最内层索引
SchoolGenderHeightWeightMathPhysics
ClassAddress
C_2street_7S_2F1947768.5B+
street_7S_2F1837685.4B
C_3street_2S_1M1957085.2A
#(c)第二类特殊情况:由列表构成元组
df_using_mul.sort_index().loc[(['C_2','C_3'],['street_4','street_7']),:]
#选出第一层在'C_2'和'C_3'中且第二层在'street_4'和'street_7'中的行
SchoolGenderHeightWeightMathPhysics
ClassAddress
C_2street_4S_1F1769463.5B-
street_4S_2M1559173.8A+
street_7S_2F1947768.5B+
street_7S_2F1837685.4B
C_3street_4S_1M1616831.5B+
street_4S_2F1577872.3B+
street_4S_2M1877348.9B
street_7S_1M1888249.7B
street_7S_2F1909965.9C
#3.多层索引中的slice对象 ?????
L1,L2=['A','B','C'],['a','b','c']
mul_index1 = pd.MultiIndex.from_product([L1,L2],names=('Upper','Lower'))
L3,L4 = ['D','E','F'],['d','e','f']
mul_index2 = pd.MultiIndex.from_product([L3,L4],names=('Big','Small'))
df_s = pd.DataFrame(np.random.rand(9,9),index=mul_index1,columns=mul_index2)
df_s
BigDEF
Smalldefdefdef
UpperLower
Aa0.9347460.8276360.3031600.4565950.1011670.4485180.9268650.2469470.007101
b0.7843000.7439200.9140710.6159050.4653860.8149350.8201460.9782390.075463
c0.2347250.5309270.3341030.7846670.4234660.7156570.0014060.1068580.858155
Ba0.4790800.1703410.8941530.7273800.6179450.2241880.0367670.5029970.761644
b0.0366780.1091760.7715350.8103770.4759530.7949770.0199680.1814140.917155
c0.2617260.6819570.8940730.9853470.3251020.1280260.2523630.5012420.907674
Ca0.6084850.8509450.4869630.7504010.3841610.6773550.9230220.5352710.918066
b0.7375640.3854850.0206640.2955690.7874610.9529170.7461520.1804810.802424
c0.0253350.5319370.2593620.5056870.7757900.1743190.5221570.0114740.001091
idx=pd.IndexSlice
df_s.loc[idx['B':,df_s['D']['d']>0.3],idx[df_s.sum()>4]]
#df_s.sum()默认为对列表求和,因此返回一个长度为9的数值列表
BigDEF
Smalldefdefdf
UpperLower
Ba0.4790800.1703410.8941530.7273800.6179450.2241880.0367670.761644
Ca0.6084850.8509450.4869630.7504010.3841610.6773550.9230220.918066
b0.7375640.3854850.0206640.2955690.7874610.9529170.7461520.802424
#4.索引层的交换
#(a) swaplevel方法(两层交换)
df_using_mul.head()
SchoolGenderHeightWeightMathPhysics
ClassAddress
C_1street_1S_1M1736334.0A+
street_2S_1F1927332.5B+
street_2S_1M1868287.2B+
street_2S_1F1678180.4B-
street_4S_1F1596484.8B+
df_using_mul.swaplevel(i=1,j=0,axis=0).sort_index().head()
SchoolGenderHeightWeightMathPhysics
AddressClass
street_1C_1S_1M1736334.0A+
C_2S_2M1757447.2B-
C_3S_1F1755787.7A-
street_2C_1S_1F1927332.5B+
C_1S_1M1868287.2B+
#(b) reorder_levels方法(多层交换)
df_muls = df.set_index(['School','Class','Address'])
df_muls.head()
GenderHeightWeightMathPhysics
SchoolClassAddress
S_1C_1street_1M1736334.0A+
street_2F1927332.5B+
street_2M1868287.2B+
street_2F1678180.4B-
street_4F1596484.8B+
df_muls.reorder_levels([2,0,1],axis=0).sort_index().head()
GenderHeightWeightMathPhysics
AddressSchoolClass
street_1S_1C_1M1736334.0A+
C_3F1755787.7A-
S_2C_2M1757447.2B-
street_2S_1C_1F1927332.5B+
C_1M1868287.2B+
# 如果索引有name,可以直接使用name
df_muls.reorder_levels(['Address','School','Class'],axis=0).sort_index().head()
GenderHeightWeightMathPhysics
AddressSchoolClass
street_1S_1C_1M1736334.0A+
C_3F1755787.7A-
S_2C_2M1757447.2B-
street_2S_1C_1F1927332.5B+
C_1M1868287.2B+

三、索引设定

#1.index_col参数   
#index_col参数时read_csv的一个参数,而不是某一个方法
pd.read_csv(r'D:\study\pandas\data\table.csv',index_col=['Address','School']).head()
ClassIDGenderHeightWeightMathPhysics
AddressSchool
street_1S_1C_11101M1736334.0A+
street_2S_1C_11102F1927332.5B+
S_1C_11103M1868287.2B+
S_1C_11104F1678180.4B-
street_4S_1C_11105F1596484.8B+
#2.reindex和reindex_like
df.head()
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1101S_1C_1Mstreet_11736334.0A+
1102S_1C_1Fstreet_21927332.5B+
1103S_1C_1Mstreet_21868287.2B+
1104S_1C_1Fstreet_21678180.4B-
1105S_1C_1Fstreet_41596484.8B+
df.reindex(index=[1101,1203,1206,2402])
#reindex是指重新索引,她的重要特性在于索引对其,很多时候用于重新排序
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1101S_1C_1Mstreet_1173.063.034.0A+
1203S_1C_2Mstreet_6160.053.058.8A+
1206NaNNaNNaNNaNNaNNaNNaNNaN
2402S_2C_4Mstreet_7166.082.048.7B
df.reindex(columns=['Height','Gender','Average']).head()
HeightGenderAverage
ID
1101173MNaN
1102192FNaN
1103186MNaN
1104167FNaN
1105159FNaN
df.reindex(index=[1101,1203,1206,2402],method='bfill')
#可选择缺失值的填充方法:fill_value和method(bfill/ffill/nearest),其中method参数必须索引单调
#bfill表示用所在索引1206的后一个有效填充,ffill为前一个有效行,mearest是指最近的

SchoolClassGenderAddressHeightWeightMathPhysics
ID
1101S_1C_1Mstreet_11736334.0A+
1203S_1C_2Mstreet_61605358.8A+
1206S_1C_3Mstreet_41616831.5B+
2402S_2C_4Mstreet_71668248.7B
df.reindex(index=[1101,1203,1206,2402],method='nearest')
#数值上1205比1301更接近1206,因此用前者填充
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1101S_1C_1Mstreet_11736334.0A+
1203S_1C_2Mstreet_61605358.8A+
1206S_1C_2Fstreet_61676368.4B-
2402S_2C_4Mstreet_71668248.7B
df_temp = pd.DataFrame({'Weight':np.zeros(5),
                      'Height':np.zeros(5),
                      'ID':[1101,1104,1103,1106,1102]}).set_index('ID')
df_temp.reindex_like(df[0:5][['Weight','Height']])
#???reindex_like的作用为生成一个横纵索引完全与参数列表一致的DataFrame,数据使用被调用的表
WeightHeight
ID
11010.00.0
11020.00.0
11030.00.0
11040.00.0
1105NaNNaN
#如果df_temp单调还可以使用method参数
df_temp = pd.DataFrame({'Weight':range(5),
                      'Height':range(5),
                      'ID':[1101,1104,1103,1106,1102]}).set_index('ID').sort_index()
df_temp.reindex_like(df[0:5][['Weight','Height']],method='bfill')
#可以自行剑演这里的105的值是否时由bfill规则填充
WeightHeight
ID
110100
110244
110322
110411
110533
#3.set_index和reset_index
df.head()
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1101S_1C_1Mstreet_11736334.0A+
1102S_1C_1Fstreet_21927332.5B+
1103S_1C_1Mstreet_21868287.2B+
1104S_1C_1Fstreet_21678180.4B-
1105S_1C_1Fstreet_41596484.8B+
#(a)set_index 将某些列作为索引
df.set_index('Class').head() #使用表内列作为索引
SchoolGenderAddressHeightWeightMathPhysics
Class
C_1S_1Mstreet_11736334.0A+
C_1S_1Fstreet_21927332.5B+
C_1S_1Mstreet_21868287.2B+
C_1S_1Fstreet_21678180.4B-
C_1S_1Fstreet_41596484.8B+
#利用append函数可以将当前索引维持不变
df.set_index('Class',append=True).head()
SchoolGenderAddressHeightWeightMathPhysics
IDClass
1101C_1S_1Mstreet_11736334.0A+
1102C_1S_1Fstreet_21927332.5B+
1103C_1S_1Mstreet_21868287.2B+
1104C_1S_1Fstreet_21678180.4B-
1105C_1S_1Fstreet_41596484.8B+
#当使用与表长相同的列作为索引(需要先转化为Series,否则报错):
df.set_index(pd.Series(range(df.shape[0]))).head()
SchoolClassGenderAddressHeightWeightMathPhysics
0S_1C_1Mstreet_11736334.0A+
1S_1C_1Fstreet_21927332.5B+
2S_1C_1Mstreet_21868287.2B+
3S_1C_1Fstreet_21678180.4B-
4S_1C_1Fstreet_41596484.8B+
#可以直接添加多级索引
df.set_index([pd.Series(range(df.shape[0])),pd.Series(np.ones(df.shape[0]))]).head()
SchoolClassGenderAddressHeightWeightMathPhysics
01.0S_1C_1Mstreet_11736334.0A+
11.0S_1C_1Fstreet_21927332.5B+
21.0S_1C_1Mstreet_21868287.2B+
31.0S_1C_1Fstreet_21678180.4B-
41.0S_1C_1Fstreet_41596484.8B+
#(b)reset_index,主要功能时将索引重置
df.reset_index().head() #默认状态直接恢复到自然数索引
IDSchoolClassGenderAddressHeightWeightMathPhysics
01101S_1C_1Mstreet_11736334.0A+
11102S_1C_1Fstreet_21927332.5B+
21103S_1C_1Mstreet_21868287.2B+
31104S_1C_1Fstreet_21678180.4B-
41105S_1C_1Fstreet_41596484.8B+
#用level参数指定哪一层被reset,用col_level参数指定set到哪一层
L1,L2 = ['A','B','C'],['a','b','c']
mul_index1 = pd.MultiIndex.from_product([L1,L2],names=('Upper','Lower'))
L3,L4 = ['D','E','F'],['d','e','f']
mul_index2 = pd.MultiIndex.from_product([L3,L4],names=('Big','Small'))
df_temp = pd.DataFrame(np.random.rand(9,9),index=mul_index1,columns=mul_index2)
df_temp.head()
BigDEF
Smalldefdefdef
UpperLower
Aa0.7264470.7930060.5067170.8998410.2138790.4526840.8907270.6968490.474411
b0.1392190.6156550.5899700.4633510.5548880.0753180.6906410.0435520.783326
c0.0282880.0912460.0459640.2236540.3441450.1731380.3451860.2145510.404022
Ba0.0166250.8010640.0020580.0427800.4842720.7365780.8000870.3913360.918262
b0.9545630.2325700.1705940.4400040.9578310.2230910.9903640.4532470.097994
df_temp1 = df_temp.reset_index(level=1,col_level=1)
df_temp1.head() #??
BigDEF
SmallLowerdefdefdef
Upper
Aa0.7264470.7930060.5067170.8998410.2138790.4526840.8907270.6968490.474411
Ab0.1392190.6156550.5899700.4633510.5548880.0753180.6906410.0435520.783326
Ac0.0282880.0912460.0459640.2236540.3441450.1731380.3451860.2145510.404022
Ba0.0166250.8010640.0020580.0427800.4842720.7365780.8000870.3913360.918262
Bb0.9545630.2325700.1705940.4400040.9578310.2230910.9903640.4532470.097994
# df_temp1.columns #看到的确插入了level2
 df_temp1.index  #最内层索引被移出
Index(['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C'], dtype='object', name='Upper')
#4.rename_axis 和 Rename
#rename_axis时针对多级索引的方法,作用是修改某一层的索引名,而不是索引标签
df_temp.rename_axis(index={'Lower':'LowerLower'},columns={'Big','BigBig'})
BigDEF
BigBigdefdefdef
UpperLowerLower
Aa0.7264470.7930060.5067170.8998410.2138790.4526840.8907270.6968490.474411
b0.1392190.6156550.5899700.4633510.5548880.0753180.6906410.0435520.783326
c0.0282880.0912460.0459640.2236540.3441450.1731380.3451860.2145510.404022
Ba0.0166250.8010640.0020580.0427800.4842720.7365780.8000870.3913360.918262
b0.9545630.2325700.1705940.4400040.9578310.2230910.9903640.4532470.097994
c0.5799130.2330980.9827240.6846700.9407870.3300790.0430150.5687280.284846
Ca0.9558090.3180910.3706190.2142610.5486560.3385550.8614260.2564950.601147
b0.0812330.0004210.9897280.9271170.2867450.4583870.3812080.3427660.384358
c0.9893510.9357470.0032500.1150690.6010640.4883680.8907400.7127040.730693
#rename方法用于修改列或行索引标签,而不是索引名
df_temp.rename(index={'A':'T'},columns={'e':'changed_e'}).head()
BigDEF
Smalldchanged_efdchanged_efdchanged_ef
UpperLower
Ta0.7264470.7930060.5067170.8998410.2138790.4526840.8907270.6968490.474411
b0.1392190.6156550.5899700.4633510.5548880.0753180.6906410.0435520.783326
c0.0282880.0912460.0459640.2236540.3441450.1731380.3451860.2145510.404022
Ba0.0166250.8010640.0020580.0427800.4842720.7365780.8000870.3913360.918262
b0.9545630.2325700.1705940.4400040.9578310.2230910.9903640.4532470.097994

四、常用索引型函数

#1.where函数
df.head()
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1101S_1C_1Mstreet_11736334.0A+
1102S_1C_1Fstreet_21927332.5B+
1103S_1C_1Mstreet_21868287.2B+
1104S_1C_1Fstreet_21678180.4B-
1105S_1C_1Fstreet_41596484.8B+
#当对条件为False的单元进行填充:
df.where(df['Gender']=='M').head()
#不满足条件的行全部被设置为NaN
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1101S_1C_1Mstreet_1173.063.034.0A+
1102NaNNaNNaNNaNNaNNaNNaNNaN
1103S_1C_1Mstreet_2186.082.087.2B+
1104NaNNaNNaNNaNNaNNaNNaNNaN
1105NaNNaNNaNNaNNaNNaNNaNNaN
#通过这种方法筛选结果和[]操作符结果完全一致
df.where(df['Gender']=='M').dropna().head() #dropna()将不满足条件的行删除
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1101S_1C_1Mstreet_1173.063.034.0A+
1103S_1C_1Mstreet_2186.082.087.2B+
1201S_1C_2Mstreet_5188.068.097.0A-
1203S_1C_2Mstreet_6160.053.058.8A+
1301S_1C_3Mstreet_4161.068.031.5B+
df.where(df['Gender']=='M',np.random.rand(df.shape[0],df.shape[1])).head()
#第一个参数为不二条件,第二个参数为填充值
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1101S_1C_1Mstreet_1173.00000063.00000034.000000A+
11020.00887420.687510.178430.5388730.7959460.8600840.4377210.929262
1103S_1C_1Mstreet_2186.00000082.00000087.200000B+
11040.05084250.2130380.7348980.14130.4411880.5166100.8967870.110277
11050.8497490.7758330.4353290.9477050.0503610.6192920.8298720.963952
# 2.mask函数
#mask函数与where功能上相反,其余完全一致,即对条件为True的单元格进行填充
df.mask(df['Gender']=='M').dropna().head()
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1102S_1C_1Fstreet_2192.073.032.5B+
1104S_1C_1Fstreet_2167.081.080.4B-
1105S_1C_1Fstreet_4159.064.084.8B+
1202S_1C_2Fstreet_4176.094.063.5B-
1204S_1C_2Fstreet_5162.063.033.8B
df.mask(df['Gender']=='M',np.random.rand(df.shape[0],df.shape[1])).head()
SchoolClassGenderAddressHeightWeightMathPhysics
ID
11010.6455950.1411150.01130810.3466160.3994270.3674680.2601310.32254
1102S_1C_1Fstreet_2192.00000073.00000032.500000B+
11030.02844720.5134030.02494960.4051560.6407640.4684730.1287660.553058
1104S_1C_1Fstreet_2167.00000081.00000080.400000B-
1105S_1C_1Fstreet_4159.00000064.00000084.800000B+
# 3.query函数  筛选查询
df.head()
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1101S_1C_1Mstreet_11736334.0A+
1102S_1C_1Fstreet_21927332.5B+
1103S_1C_1Mstreet_21868287.2B+
1104S_1C_1Fstreet_21678180.4B-
1105S_1C_1Fstreet_41596484.8B+
df.query('(Address in ["street_6","street_7"])&(Weight>(70+10))&(ID in [1303,2304,2402])')
#query函数中的布尔表达式中,以下符号都是合法的:
#行列索引名,字符串,and/not/or/&/|/~/not in/in/==/!=、四则运算符
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1303S_1C_3Mstreet_71888249.7B
2304S_2C_3Fstreet_61648195.5A-
2402S_2C_4Mstreet_71668248.7B

五、重复元素处理

#1、duplicated方法:返回了是否重复的布尔列表
df.duplicated('Class').head()
ID
1101    False
1102     True
1103     True
1104     True
1105     True
dtype: bool
#可选参数keep默认为first,即首次出现设为不重复,若为Last,则最后一次设为不重复,若为False,则所有重复项为True
df.duplicated('Class',keep='last').tail()
ID
2401     True
2402     True
2403     True
2404     True
2405    False
dtype: bool
df.duplicated('Class',keep=False).head()
ID
1101    True
1102    True
1103    True
1104    True
1105    True
dtype: bool
# 2.drop_duplicates方法 剔除重复项
df.drop_duplicates('Class')
#在分组操作中可能是有用的,例如需要保留每组的第一个值
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1101S_1C_1Mstreet_11736334.0A+
1201S_1C_2Mstreet_51886897.0A-
1301S_1C_3Mstreet_41616831.5B+
2401S_2C_4Fstreet_21926245.3A
df.drop_duplicates('Class',keep='last') #参数与duplicate函数类似
SchoolClassGenderAddressHeightWeightMathPhysics
ID
2105S_2C_1Mstreet_41708134.2A
2205S_2C_2Fstreet_71837685.4B
2305S_2C_3Mstreet_41877348.9B
2405S_2C_4Fstreet_61935447.6B
df.drop_duplicates(['School','Class'])
#在传入多列时等价于将多列共同视作一个多级索引,比较重复项
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1101S_1C_1Mstreet_11736334.0A+
1201S_1C_2Mstreet_51886897.0A-
1301S_1C_3Mstreet_41616831.5B+
2101S_2C_1Mstreet_71748483.3C
2201S_2C_2Mstreet_519310039.1B
2301S_2C_3Fstreet_41577872.3B+
2401S_2C_4Fstreet_21926245.3A

六、抽样函数(sample)

# (a)n为样本量
df.sample(n=5)
SchoolClassGenderAddressHeightWeightMathPhysics
ID
2301S_2C_3Fstreet_41577872.3B+
1202S_1C_2Fstreet_41769463.5B-
2104S_2C_1Fstreet_51599772.2B+
1101S_1C_1Mstreet_11736334.0A+
2401S_2C_4Fstreet_21926245.3A
# (b)frac为抽样比
df.sample(frac=0.05)
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1301S_1C_3Mstreet_41616831.5B+
2301S_2C_3Fstreet_41577872.3B+
# (c) replace为是否放回
df.sample(n=df.shape[0],replace=True).head()
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1103S_1C_1Mstreet_21868287.2B+
2402S_2C_4Mstreet_71668248.7B
2402S_2C_4Mstreet_71668248.7B
1203S_1C_2Mstreet_61605358.8A+
1103S_1C_1Mstreet_21868287.2B+
df.sample(n=35,replace=True).index.is_unique
False
# (d)axis为抽样维度,默认为0,即抽行  1抽列
df.sample(n=3,axis=1).head()
MathWeightPhysics
ID
110134.063A+
110232.573B+
110387.282B+
110480.481B-
110584.864B+
# (e)weights为样本权重,自动归一化
df.sample(n=3,weights=np.random.rand(df.shape[0])).head()
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1101S_1C_1Mstreet_11736334.0A+
2205S_2C_2Fstreet_71837685.4B
2102S_2C_1Fstreet_61616150.6B+
#以某一列为权重,这样在抽样理论中很常见
df.sample(n=3,weights=df['Math']).head()
SchoolClassGenderAddressHeightWeightMathPhysics
ID
1201S_1C_2Mstreet_51886897.0A-
2304S_2C_3Fstreet_61648195.5A-
2301S_2C_3Fstreet_41577872.3B+

七、问题与练习

#【问题一】 如何更改列或行的顺序?如何交换奇偶行(列)的顺序?
#【问题二】 如果要选出DataFrame的某个子集,请给出尽可能多的方法实现。

#【问题三】 query函数比其他索引方法的速度更慢吗?在什么场合使用什么索引最高效?
1
#【问题四】 单级索引能使用Slice对象吗?能的话怎么使用,请给出一个例子。

#【问题五】 如何快速找出某一列的缺失值所在索引?
#【问题六】 索引设定中的所有方法分别适用于哪些场合?怎么直接把某个DataFrame的索引换成任意给定同长度的索引?
#【问题七】 多级索引有什么适用场合?
#【问题八】 什么时候需要重复元素处理?

#【练习一】 现有一份关于UFO的数据集,请解决下列问题
#(a)在所有被观测时间超过60s的时间中,哪个形状最多?
df= pd .read_csv(r'D:\study\pandas\data\UFO.csv')
df.rename(columns={'duration (seconds)':'duration'},inplace=True)
#df['duration'].astype('float')  
df.head()
datetimeshapedurationlatitudelongitude
010/10/1949 20:30cylinder2700.029.883056-97.941111
110/10/1949 21:00light7200.029.384210-98.581082
210/10/1955 17:00circle20.053.200000-2.916667
310/10/1956 21:00circle20.028.978333-96.645833
410/10/1960 20:00light900.021.418056-157.803611
df.query('duration > 60')['shape'].value_counts().index[0]
'light'
#(b)对经纬度进行划分:-180°至180°以30°为一个划分,-90°至90°以18°为一个划分,请问哪个区域中报告的UFO事件数量最多?
bins_long = np.linspace(-180,180,13).tolist()
bins_la = np.linspace(-90,90,11).tolist()
cuts_long = pd.cut(df['longitude'],bins=bins_long)
df['cuts_long'] =cuts_long
cuts_la = pd.cut(df['latitude'],bins=bins_la)
df['cuts_la'] = cuts_la
df.head()
datetimeshapedurationlatitudelongitudecuts_longcuts_la
010/10/1949 20:30cylinder2700.029.883056-97.941111(-120.0, -90.0](18.0, 36.0]
110/10/1949 21:00light7200.029.384210-98.581082(-120.0, -90.0](18.0, 36.0]
210/10/1955 17:00circle20.053.200000-2.916667(-30.0, 0.0](36.0, 54.0]
310/10/1956 21:00circle20.028.978333-96.645833(-120.0, -90.0](18.0, 36.0]
410/10/1960 20:00light900.021.418056-157.803611(-180.0, -150.0](18.0, 36.0]
df.set_index(['cuts_long','cuts_la']).index.value_counts().head()
((-90.0, -60.0], (36.0, 54.0])      27891
((-120.0, -90.0], (18.0, 36.0])     14280
((-120.0, -90.0], (36.0, 54.0])     11960
((-90.0, -60.0], (18.0, 36.0])       9923
((-150.0, -120.0], (36.0, 54.0])     9658
dtype: int64
#【练习二】 现有一份关于口袋妖怪的数据集,请解决下列问题:
df=pd.read_csv(r'D:\study\pandas\data\Pokemon.csv')
df.head()
#NameType 1Type 2TotalHPAttackDefenseSp. AtkSp. DefSpeedGenerationLegendary
01BulbasaurGrassPoison3184549496565451False
12IvysaurGrassPoison4056062638080601False
23VenusaurGrassPoison525808283100100801False
33VenusaurMega VenusaurGrassPoison62580100123122120801False
44CharmanderFireNaN3093952436050651False
#(a)双属性的Pokemon占总体比例的多少
df['Type 2'].count()/df.shape[0]
0.5175
#(b)在所有种族值(Total)不小于580的Pokemon中,非神兽(Legendary=False)的比例为多少?
df.query('Total>=580')['Legendary'].value_counts(normalize=True)
#42.48%
True     0.575221
False    0.424779
Name: Legendary, dtype: float64
#(c)在第一属性为格斗系(Fighting)的Pokemon中,物攻排名前三高的是哪些?
df[df['Type 1']=='Fighting'].sort_values(by='Attack',ascending=False).iloc[:3]
#NameType 1Type 2TotalHPAttackDefenseSp. AtkSp. DefSpeedGenerationLegendary
498448LucarioMega LucarioFightingSteel6257014588140701124False
594534ConkeldurrFightingNaN505105140955565455False
7468MachampFightingNaN50590130806585551False
#(d)请问六项种族指标(HP、物攻、特攻、物防、特防、速度)极差的均值最大的是哪个属性(只考虑第一属性,且均值是对属性而言)?
df['range'] = df.iloc[:,5:11].max(axis=1)-df.iloc[:,5:11].min(axis=1)
attribute= df[['Type 1','range']].set_index('Type 1')
max_range = 0
result = ' '
for i in attribute.index.unique():
    temp = attribute.loc[i,:].mean()
    if temp.values[0] > max_range:
        max_range = temp.values[0]
        result = i
result
'Steel'
#(e)哪个属性(只考虑第一属性)的神兽比例最高?该属性神兽的种族值也是最高的吗?
df.query('Legendary ==True')['Type 1'].value_counts(normalize=True).index[0]
'Psychic'
attribute = df.query('Legendary == True')[['Type 1','Total']].set_index('Type 1')
max_value = 0
result = ''
for i in attribute.index.unique():
    temp = float(attribute.loc[i,:].mean())
    if temp > max_value:
        max_value = temp
        result = i
result
#超能系占比最高,但普通系均值最高
'Normal'

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值