5 pandas 单级索引 loc,iloc,[]+区间索引


单级索引有:loc标签索引、iloc位置索引、[]

loc 本质:loc中能传入的只有布尔列表索引子集构成的列表。
iloc本质:iloc中接收的参数只能为整数或整数列表或布尔列表,不能使用布尔Series,如果要用就必须把values拿出来。
双冒号::最后一个位置是步长,::2 表示间隔2取元素。
一般来说,[]操作符常用于列选择布尔选择,尽量避免行的选择

记住loc和iloc就能实现大部分功能了,[ ]的用法有些混乱。

单行,多行,切片,函数式,布尔。

函数:

  • all()方法,any()方法

  • 默认axis=0,即跨行,all()判断这一列的值是否全真,全真返回True。any()有一个真就返回Ture。

  • all(1)是给axis传了1,即跨列运算,一行全True就返回True。

  • join()合并方法,合并那章会讲。

  • reset_index()方法,就是把原df的index变成列,现在index设置成0开始的整数。

  • set_index(列名) 就是取一列作为index。

  • 想要交换index列和某一数值列,.reset_index().set_indedx(列名)

  • astype(类型)方法可以转换数据类型。里面的类型要是字符串形式,比如df.index.astype(‘interval’).

一、 loc 标签索引

  • 行索引
print(df.loc[1105])  # 1单行
print()
print(df.loc[[1101, 1105]])  # 2多行,需要里面再加一个[]
print()
print(df.loc[1110:1220])  # 切片,dataframe的切片是左闭右闭
print()
print(df.loc[2402::-1].head())  # 注意中间两个冒号,-1表示步长
School          S_1
Class           C_1
Gender            F
Address    street_4
Height          159
Weight           64
Math           84.8
Physics          B+
Name: 1105, dtype: object

     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1101    S_1   C_1      M  street_1     173      63  34.0      A+
1105    S_1   C_1      F  street_4     159      64  84.8      B+

     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1201    S_1   C_2      M  street_5     188      68  97.0      A-
1202    S_1   C_2      F  street_4     176      94  63.5      B-
1203    S_1   C_2      M  street_6     160      53  58.8      A+
1204    S_1   C_2      F  street_5     162      63  33.8       B
1205    S_1   C_2      F  street_6     167      63  68.4      B-

     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
2402    S_2   C_4      M  street_7     166      82  48.7       B
2401    S_2   C_4      F  street_2     192      62  45.3       A
2305    S_2   C_3      M  street_4     187      73  48.9       B
2304    S_2   C_3      F  street_6     164      81  95.5      A-
2303    S_2   C_3      F  street_7     190      99  65.9       C
  • 列索引
print(df.loc[:, 'Height'].head())  # 单列
print(df.loc[:, ['Height', 'Weight']].head())  # 多列,还是要用[]括起来
print(df.loc[:, 'Height':'Math'].head()) # 切片
ID
1101    173
1102    192
1103    186
1104    167
1105    159
Name: Height, dtype: int64
      Height  Weight
ID                  
1101     173      63
1102     192      73
1103     186      82
1104     167      81
1105     159      64
      Height  Weight  Math
ID                        
1101     173      63  34.0
1102     192      73  32.5
1103     186      82  87.2
1104     167      81  80.4
1105     159      64  84.8
  • 联合索引
print(df.loc[1104:2401, 'Height':'Math'].head())
      Height  Weight  Math
ID                        
1104     167      81  80.4
1105     159      64  84.8
1201     188      68  97.0
1202     176      94  63.5
1203     160      53  58.8
  • 函数式索引
print(df.loc[lambda x: x['Gender'] == 'F'].head())
# 等价于下面
# print(df.loc[df['Gender']=='F'])
    School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1102    S_1   C_1      F  street_2     192      73  32.5      B+
1104    S_1   C_1      F  street_2     167      81  80.4      B-
1105    S_1   C_1      F  street_4     159      64  84.8      B+
1202    S_1   C_2      F  street_4     176      94  63.5      B-
1204    S_1   C_2      F  street_5     162      63  33.8       B
  • 布尔索引★★
    loc的布尔索引,可以传一个dtype是 " 布尔值的Series " ,也可以是一个" ndarray " 或者 " 列表 " 。
print(df.loc[df['Address'].isin(['street_7', 'street_4'])].head())
print(df.loc[[True if x[-1] in '47' else False for x in df['Address']]].head())
# 上面两个结果一样
    School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1105    S_1   C_1      F  street_4     159      64  84.8      B+
1202    S_1   C_2      F  street_4     176      94  63.5      B-
1301    S_1   C_3      M  street_4     161      68  31.5      B+
1303    S_1   C_3      M  street_7     188      82  49.7       B
2101    S_2   C_1      M  street_7     174      84  83.3       C
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1105    S_1   C_1      F  street_4     159      64  84.8      B+
1202    S_1   C_2      F  street_4     176      94  63.5      B-
1301    S_1   C_3      M  street_4     161      68  31.5      B+
1303    S_1   C_3      M  street_7     188      82  49.7       B
2101    S_2   C_1      M  street_7     174      84  83.3       C

二、iloc 位置索引

  • 行索引
# 行索引
print(df.iloc[3])  # 单行
print(df.iloc[[3, 5]])  # 多行
print(df.iloc[3:5])  # 切片
School          S_1
Class           C_1
Gender            F
Address    street_2
Height          167
Weight           81
Math           80.4
Physics          B-
Name: 1104, dtype: object
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1104    S_1   C_1      F  street_2     167      81  80.4      B-
1201    S_1   C_2      M  street_5     188      68  97.0      A-
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1104    S_1   C_1      F  street_2     167      81  80.4      B-
1105    S_1   C_1      F  street_4     159      64  84.8      B+

  • 列索引
print(df.iloc[:, 3].head())  # 单列
print(df.iloc[:, 7::-2].head())  # 多列
  • 混合索引
print(df.iloc[::2, 7::-2].head())
  • 函数式索引
print(df.iloc[lambda x: [3]])
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1104    S_1   C_1      F  street_2     167      81  80.4      B-
  • 布尔索引★

iloc中接收的参数只能为 整数 或 整数列表 或 布尔列表,不能使用 布尔Series,如果要用就必须如下把values拿出来

print(df.iloc[(df['Gender'] == 'M').values].head())
# print(df.iloc[df['Gender']=='M'].head()) 错!!报错如下
# NotImplementedError: iLocation based boolean indexing on an integer type is not available

三、[]操作符

Series的[]

总结:不要用[]对Series和DataFrame进行行行索引了…记不住用法,都用loc和iloc得了。

注意:Series也是可以用loc和iloc的。

DataFrame的[ ] 只有位置索引没有标签索引
将df的一列拿出来做Series,index还是df的index:

s = pd.Series(df['Math'], index=df.index)
  • 下面看Series行索引【Series也只有行索引,因为本来就只有一列
# Series的[]
s = pd.Series(df['Math'], index=df.index)
print(s[1101])  # 标签索引,单元素
print(s[0:4])  # 使用的是位置切片
# print(s[0])  # 报错,Series没有这样的位置索引
# print(s[0,2]) # 报错

print(s[lambda x: x.index[16::-6]])  # 函数索引
# 下面没懂
# 注意使用lambda函数时,直接切片(如:s[lambda x: 16::-6])就报错,此时使用的不是绝对位置切片,而是元素切片,非常易错
  • 布尔索引
# 布尔索引
print((s > 80).head())
print(s[s > 80].head())
ID
1101    False
1102    False
1103     True
1104     True
1105     True
Name: Math, dtype: bool
ID
1103    87.2
1104    80.4
1105    84.8
1201    97.0
1302    87.7
Name: Math, dtype: float64
  • 下面不好记。
# 【注意】如果不想陷入困境,请不要在行索引为浮点时使用[]操作符,因为在Series中[]的浮点切片并不是进行位置比较,而是值比较,非常特殊
s_int = pd.Series([1, 2, 3, 4], index=[1, 3, 5, 6])
s_float = pd.Series([1, 2, 3, 4], index=[1., 3., 5., 6.])
print(s_int[2:])  # 这里2就是索引
print(s_float[2:])  # 这里2是元素

DataFrame的[]

  • 总结:只用[]用来dataframe的列索引就好了,行索引的用法很麻烦。一般来说,[]操作符常用于列选择或布尔选择,尽量避免行的选择
  • 单行索引,注意,非常特殊,只能使用位置索引,必须写成切片的样子,不然会以为是列索引,报错.
  • **注意,**没有df[‘label’]的写法,这种写法是应该用于loc. 所以,dataframe关于[]的行索引只有位置索引,没有标签索引。
print(df[1:2]) 
  • 如果非要使用label+[]来获取行的话:先得到这个label的位置索引,再利用[]取行.
row = df.index.get_loc(1102)  # 该函数返回label的位置索引
print(df[row:row + 1])
  • 多行索引,只有切片形式
# 多行索引,切片形式,如果想选指定的,隔开的几行,推荐使用loc,使用[]容易报错
print(df[2:5])
  • 列索引
# 单列索引
print(df['School'].head())

# 多列索引
print(df[['School', 'Math']].head())  # 同loc和iloc,需要多套一个[]
  • 函数式
# 函数式索引
print(df[lambda x: ['Math', 'Physics']].head())
  • 布尔索引★
print(df[df['Gender'] == 'F'].head())  # 和loc,iloc的差不多,反正就是对一列的值进行判断,返回bool值,然后根据返回的bool型Series挑出来行

四、布尔索引

布尔符号 & | ~,用于布尔数据间的运算.
原理:loc,iloc,[]都可以使用bool索引,都是传一个一维的bool序列,然后根据这个布尔序列取出符合条件的行。
需要注意的是,iloc接受不了Series类型的bool序列,但是可以使用.values将这个Series转换为ndarray,就可以了。
至于loc和[]的布尔索引,使用方法相同。

使用布尔运算符

  • 一个位置的。
print('&:')
print(df.iloc[((df['Gender'] == 'F') & (df['Address'] == 'street_2')).values].head())
print('|:')
print(df[(df['Math'] > 85) | (df['Address'] == 'street_1')].head())
print('~:')
print(df[(~(df['Physics'] == 'B-') | (df['Gender'] == 'M'))].head())
&:
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1102    S_1   C_1      F  street_2     192      73  32.5      B+
1104    S_1   C_1      F  street_2     167      81  80.4      B-
2401    S_2   C_4      F  street_2     192      62  45.3       A
2404    S_2   C_4      F  street_2     160      84  67.7       B
|:
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1101    S_1   C_1      M  street_1     173      63  34.0      A+
1103    S_1   C_1      M  street_2     186      82  87.2      B+
1201    S_1   C_2      M  street_5     188      68  97.0      A-
1302    S_1   C_3      F  street_1     175      57  87.7      A-
1304    S_1   C_3      M  street_2     195      70  85.2       A
~:
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1101    S_1   C_1      M  street_1     173      63  34.0      A+
1102    S_1   C_1      F  street_2     192      73  32.5      B+
1103    S_1   C_1      M  street_2     186      82  87.2      B+
1105    S_1   C_1      F  street_4     159      64  84.8      B+
1201    S_1   C_2      M  street_5     188      68  97.0      A-
  • 两个位置的,loc和[]中两个位置都可以进行bool索引
# loc和[]中两个位置都可以进行bool索引
# df.columns == 'physics'是一个dtype为bool的ndarray,并且是一维的行向量
print(df.loc[df['Math'] > 60, df.columns == 'Physics'].head())
     Physics
ID          
1103      B+
1104      B-
1105      B+
1201      A-
1202      B-

isin()方法

# 有两个条件,一般思路写法:将两个series序列用&运算符先计算,然后再取布尔索引
print(df[df.loc[:, 'Address'].isin(['street_1', 'street_4']) & df['Physics'].isin(['A', 'A+'])].head())
# 使用字典的写法:先把两列都取出来,也是用isin()判断,但是返回的是两列的布尔值dataframe,需要使用all()方法对这两列进行运算,变成一维的Series。
# 注意all()方法默认axis=0,即默认跨行运算,现在要传参数1,因为我们想跨列运算。
print(df[df[['Address', 'Physics']].isin({'Address': ['street_1', 'street_4'], 'Physics': ['A', 'A+']}).all(1)])
isin:
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1101    S_1   C_1      M  street_1     173      63  34.0      A+
2105    S_2   C_1      M  street_4     170      81  34.2       A
2203    S_2   C_2      M  street_4     155      91  73.8      A+
     School Class Gender   Address  Height  Weight  Math Physics
ID                                                              
1101    S_1   C_1      M  street_1     173      63  34.0      A+
2105    S_2   C_1      M  street_4     170      81  34.2       A
2203    S_2   C_2      M  street_4     155      91  73.8      A+

五、快速标量索引,at标签索引 和 iat位置索引

  • 当只需要取一个元素时,at和iat方法能够提供更快的实现
  • 可以使用timeit计算对比一下时间
print(df.at[1101, 'School'])
print(df.loc[1101, 'School'])
print(df.iat[5, 5])
print(df.iloc[5, 5])

S_1
S_1
68
68

六、区间索引

a. interval_range()方法

感觉现在还没有特别体会到区间索引的作用,感觉如果要提取数据在一个区间的行的话,布尔索引完全可以实现。

Interval()方法用来生成一个区间,数据类型就是interval。
interval_range()方法,生成区间,可以指定起始,终止,步长,区间数。periods参数控制区间个数,freq控制步长。
closed参数可选’left’‘right’‘both’‘neither’,默认左开右闭(上面两个方法都有这个参数)

print(pd.Interval(70, 85, closed='left'))  # interval用来生成一个区间
# closed参数可选'left''right''both''neither',默认左开右闭
# periods参数控制区间个数,freq控制步长
print(pd.interval_range(start=0, periods=10, freq=5, closed='both'))
print(pd.interval_range(start=0, end=5, periods=2, closed='neither'))
[70, 85)
IntervalIndex([[0, 5], [5, 10], [10, 15], [15, 20], [20, 25], [25, 30], [30, 35], [35, 40], [40, 45], [45, 50]],
              closed='both',
              dtype='interval[int64]')
IntervalIndex([(0.0, 2.5), (2.5, 5.0)],
              closed='neither',
              dtype='interval[float64]')

b. cut()方法将数值转为区间变量

比如现在要统计df种的数学成绩,把成绩在某些区间的行挑出来。
先提取df[‘Math’]这一列,然后使用cut()方法将这一列的值转换成区间值。

math_interval = pd.cut(df['Math'], bins=[0, 40, 60, 80, 100])
print(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]]
  • 注意上面cut返回的数据类型是category。
  • 现在想将math_interval当作索引。
  • 先join,再取出’Math’, 'Math_interval’两列,然后将’Math_interva当作索引,但是保留原来的索引ID,就是下面的写法:
df_i = df.join(math_interval, rsuffix='_interval')[['Math', 'Math_interval']].reset_index().set_index('Math_interval')
print(df_i.head())
                 ID  Math
Math_interval            
(0, 40]        1101  34.0
(0, 40]        1102  32.5
(80, 100]      1103  87.2
(80, 100]      1104  80.4
(80, 100]      1105  84.8
  • 用一个数对df_i进行索引,区间包含该数就会被选中。
print(df_i.head())
print(df_i.loc[65])  # 包含该值就会被选中
print(df_i.loc[[65, 90]].head())  # 包含这两个值就会被选中
                 ID  Math
Math_interval            
(60, 80]       1202  63.5
(60, 80]       1205  68.4
(60, 80]       1305  61.7
(60, 80]       2104  72.2
(60, 80]       2202  68.5
(60, 80]       2203  73.8
(60, 80]       2301  72.3
(60, 80]       2303  65.9
(60, 80]       2404  67.7
                 ID  Math
Math_interval            
(60, 80]       1202  63.5
(60, 80]       1205  68.4
(60, 80]       1305  61.7
(60, 80]       2104  72.2
(60, 80]       2202  68.5
  • 想把和某个区间重叠的行都给选出来【其实感觉这个例子是布尔索引…】
# 如果想要选取某个区间,先要把分类变量转为区间变量,再使用overlap方法[其实这是布尔索引了]
# 上面的思路就是:想用一个区间索引出df_i的行,但是不能直接df_i[区间](会报错),所以就只用overlap
# df_i[pd.Interval(60, 80, closed='right')] # 报错
# 说要转化为区间变量的意思是,df_i的index虽然是区间组成,但数据类型还是indexes.category,需要装换成interval的数据类型
print(df[df_i.index.astype('interval').overlaps(pd.Interval(70, 85))])
# 上面的df_i.index.astype('interval').overlaps(pd.Interval(70, 85))是布尔类型
# astype()方法可以转换数据类型
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值