pandas 删除、索引及切片
一、轴向上删除条目
通过drop方法,可以删除Series的一个元素,或者DataFrame的一行或一列。默认情况下,drop方法按行删除,且不会修改原数据,但指定axis=1则按列删除,指定inplace=True则修改原数据。
In [9]: s= pd.Series(np.arange(5),index=list('abcde'))
In [10]: s
Out[10]:
a 0
b 1
c 2
d 3
e 4
dtype: int32
In [11]: new_s = s.drop('c')
In [12]: new_s
Out[12]:
a 0
b 1
d 3
e 4
dtype: int32
In [13]: s
Out[13]:
a 0
b 1
c 2
d 3
e 4
dtype: int32
In [14]: df = pd.DataFrame(np.arange(16).reshape(4,4),columns=['one','two','three','four'])
In [15]: df
Out[15]:
one two three four
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
3 12 13 14 15
In [16]: df.drop(2)
Out[16]:
one two three four
0 0 1 2 3
1 4 5 6 7
3 12 13 14 15
In [17]: df.drop('two',axis = 1) # 指定删除列,而不是默认的行
Out[17]:
one three four
0 0 2 3
1 4 6 7
2 8 10 11
3 12 14 15
In [18]: df
Out[18]:
one two three four
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
3 12 13 14 15
In [21]: df.drop(2,inplace=True) #修改原数据
In [22]: df
Out[22]:
one two three four
0 0 1 2 3
1 4 5 6 7
3 12 13 14 15
二、索引和切片
Series的打印效果,让我们感觉它像个二维表格,实际上它还是一维的,其索引和numpy的一维数组比较类似,但还是有点区别的。
In [23]: se = pd.Series(np.linspace(1,4,5),index=list('abcde'))
In [24]: se
Out[24]:
a 1.00
b 1.75
c 2.50
d 3.25
e 4.00
dtype: float64
In [28]: se['b'] # 利用我们专门指定的索引进行检索
Out[28]: 1.75
In [29]: se[2] # 实际上默认还有一个从0开始的索引供我们使用
Out[29]: 2.5
In [30]: se[2:4]
Out[30]:
c 2.50
d 3.25
dtype: float64
In [31]: se[['b','a','d']] # 根据索引顺序,值进行相应的排序,而不是我们认为的按原来的顺序
Out[31]:
b 1.75
a 1.00
d 3.25
dtype: float64
In [32]: se[[1,3]] # 左闭右开 ,千万不要写成se[1,3]
Out[32]:
b 1.75
d 3.25
dtype: float64
In [33]: se[se>2]
Out[33]:
c 2.50
d 3.25
e 4.00
dtype: float64
In [35]: se['b':'c'] # 什么!居然是左闭右也闭!
Out[35]:
b 1.75
c 2.50
dtype: float64
In [36]: se['b':'c'] = 6 # 这样会修改原Series
In [37]: se
Out[37]:
a 1.00
b 6.00
c 6.00
d 3.25
e 4.00
dtype: float64
注意:如果你的Series是显式的整数索引,那么s[1]
这样的取值操作会使用显式索引,而s[1:3]
这样的切片操作却会使用隐式索引。
In [21]: s = pd.Series(['a','b','c'], index=[1,3,5])
In [22]: s
Out[22]:
1 a
3 b
5 c
dtype: object
In [23]: s[1]
Out[23]: 'a'
In [24]: s[1:3]
Out[24]:
3 b
5 c
dtype: object
对于DataFrame这种二维表格,情况有点不太一样,请务必注意!
核心思维:在DataFrame中,优先按列操作!
In [38]: df = pd.DataFrame(np.arange(16).reshape(4,4),
index=list('abcd'),columns=['one','two','three','four'])
In [39]: df
Out[39]:
one two three four
a 0 1 2 3
b 4 5 6 7
c 8 9 10 11
d 12 13 14 15
In [40]: df['two'] # 对于DataFrame默认是按列索引
Out[40]:
a 1
b 5
c 9
d 13
Name: two, dtype: int32
In [41]: df['b'] # KeyError,不能直接按行索引
In [43]: df[['one','four']]
Out[43]:
one four
a 0 3
b 4 7
c 8 11
d 12 15
In [44]: df[:2] # 什么!切片的时候居然是按行进行!
Out[44]:
one two three four
a 0 1 2 3
b 4 5 6 7
In [46]: df['c':'d'] # 注意闭合区间
Out[46]:
one two three four
c 8 9 10 11
d 12 13 14 15
In [47]: df ['one':'three'] # 试图用列索引来切片,但明显后台按行索引去找了,没找到。
Out[47]:
Empty DataFrame
Columns: [one, two, three, four]
Index: []
In [48]: df < 5
Out[48]:
one two three four
a True True True True
b True False False False
c False False False False
d False False False False
In [49]: df[df<5] = 0 # 这一波操作和numpy很类似
In [50]: df
Out[50]:
one two three four
a 0 0 0 0
b 0 5 6 7
c 8 9 10 11
d 12 13 14 15
是不是觉得好难理解记忆?还是numpy那种索引方式更符合人的思维习惯?没关系,Pandas考虑到了这一点,提供了类似numpy的行+列的索引标签,也就是loc和iloc。这两者差一个字母i。后者是以隐含的整数索引值来索引的,前者则使用你指定的显式的索引来定位值。
In [50]: df
Out[50]:
one two three four
a 0 0 0 0
b 0 5 6 7
c 8 9 10 11
d 12 13 14 15
In [51]: df.loc['b', ['two','four']] # 使用显式索引值,用逗号分隔行和列参数
Out[51]:
two 5
four 7
Name: b, dtype: int32
In [53]: df.loc['b':, 'two':'four'] # 切片方式,注意区间
Out[53]:
two three four
b 5 6 7
c 9 10 11
d 13 14 15
In [54]: df.iloc[2, [3, 0, 1]] # 用隐含的整数索引检索,但是这个打印格式好别扭
Out[54]:
four 11
one 8
two 9
Name: c, dtype: int32
In [55]: df.iloc[2]
Out[55]:
one 8
two 9
three 10
four 11
Name: c, dtype: int32
In [56]: df.iloc[1:,2:3] # 注意区间
Out[56]:
three
b 6
c 10
d 14
In [57]: df.iloc[:,:3][df.three>5] # 先切片,再布尔判断
Out[57]:
one two three
b 0 5 6
c 8 9 10
d 12 13 14