8.12.数据处理
Windows 10
Python 3.7.3 @ MSC v.1915 64 bit (AMD64)
Latest build date 2020.04.12
numpy version: 1.18.1
ary = copy.deepcopy(np.arange(16).reshape(4,4))
ary
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
获取符合条件的元素的索引
最大元素的索引
print(np.argmax(ary))
print(np.argmax(ary, axis=1))
print(ary.argmax(axis=1))
15
[3 3 3 3]
[3 3 3 3]
如果只是想找出最大值:
print(np.amax(ary))
# np.max是np.amax的别名
print(np.max(ary, axis=0))
print(ary.max())
print(ary.max(axis=0))
15
[12 13 14 15]
15
[12 13 14 15]
最小元素的索引
np.argmin(ary)
0
如果只是想找出最小值:
np.amin(ary)
0
按大小排序的索引
np.argsort(a, axis=-1, kind=None, order=None)
-
kind
:'quicksort', 'mergesort', 'heapsort', 'stable'
。指定排序算法。默认为'quicksort'
。 -
order
:如果是结构化数组,可以用order
参数指定按照数组的字段顺序排序。
ary2 = np.array([1, 4, 3, 2, 0, 9, 8, 5, 7])
# 由小到大排序
ary2.argsort()
ary2[ary2.argsort()]
array([0, 1, 2, ..., 7, 8, 9])
np.argpartition(a, kth, axis=-1, kind='introselect', order=None)
-
kth
:从小到大排序前kth
个元素。因为是不完全排序,因此比argsort
的效果更高。 -
kind
:'introselect'
。指定排序算法。默认为'introselect'
。 -
order
:如果是结构化数组,可以用order
参数指定按照数组的字段顺序排序。
ary2 = np.array([1, 4, 3, 2, 0, 9, 8, 5, 7])
# kth 为非负数: 从小到大排序
print(ary2.argpartition(2))
print(ary2[ary2.argpartition(2)])
# kth 为负数: 从大到小排序
print(ary2[ary2.argpartition(-2)])
[4 0 3 ... 6 7 8]
[0 1 2 ... 8 5 7]
[0 1 5 ... 7 8 9]
非零数的索引
np.nonzero
会返回非零元素的索引(这意味着nan
的索引也会被返回)。
print("符合条件的索引:")
pprint.pprint(np.nonzero(ary))
# ary.nonzero()
ary[np.nonzero(ary)]
符合条件的索引:
(array([0, 0, 0, ..., 3, 3, 3], dtype=int64),
array([1, 2, 3, ..., 1, 2, 3], dtype=int64))
array([ 1, 2, 3, ..., 13, 14, 15])
指定条件
np.where(condition)
,当condition为真,则返回元素的索引:
print("符合条件的索引:")
pprint.pprint(np.where(ary>5))
ary[np.where(ary>5)]
符合条件的索引:
(array([1, 1, 2, ..., 3, 3, 3], dtype=int64),
array([2, 3, 0, ..., 1, 2, 3], dtype=int64))
array([ 6, 7, 8, ..., 13, 14, 15])
np.where(condition)
实际上是np.asarray(condition).nonzero()
的快捷方式。
ary[np.asarray(ary>5).nonzero()]
array([ 6, 7, 8, ..., 13, 14, 15])
如果只是想得到符合条件的元素,不需要索引,使用mask数组是一个方便的方法:
pprint.pprint(ary>5)
ary[ary>5]
# np.nanargmax(ary)
array([[False, False, False, False],
[False, False, True, True],
[ True, True, True, True],
[ True, True, True, True]])
array([ 6, 7, 8, ..., 13, 14, 15])
缺失值处理
nan_ary = np.arange(16, dtype=np.float32).reshape(4,4)
nan_ary[3,2] = np.NAN
nan_ary[1,1] = np.nan
nan_ary
array([[ 0., 1., 2., 3.],
[ 4., nan, 6., 7.],
[ 8., 9., 10., 11.],
[12., 13., nan, 15.]], dtype=float32)
使用np.isnan
ufunc 函数得到mask数组:
np.isnan(nan_ary)
array([[False, False, False, False],
[False, True, False, False],
[False, False, False, False],
[False, False, True, False]])
这样就可以轻松地将nan
填充为常量:
nan_ary[np.isnan(nan_ary)]
# nan_ary[np.isnan(nan_ary)] = 2
array([nan, nan], dtype=float32)
如果想得到nan
值的索引:
np.where(np.isnan(nan_ary))
(array([1, 3], dtype=int64), array([1, 2], dtype=int64))
如果想丢弃存在nan
值的行:
np.delete(nan_ary, np.where(np.isnan(nan_ary))[0], axis=0)
array([[ 0., 1., 2., 3.],
[ 8., 9., 10., 11.]], dtype=float32)
统计存在nan
值的行(样本)所占的比列也很简单:
len(np.where(np.isnan(nan_ary))[0]) / nan_ary.shape[0]
0.5
如果想将nan
值填充为非常量(比如平均值、中位数等),这就要先计算出平均值,再对nan
数据逐个进行填充。
填充边缘
np.pad(nan_ary, pad_width=1, mode="mean")
array([[ nan, 6. , nan, nan, 9. , nan],
[ 1.5, 0. , 1. , 2. , 3. , 1.5],
[ nan, 4. , nan, 6. , 7. , nan],
[ 9.5, 8. , 9. , 10. , 11. , 9.5],
[ nan, 12. , 13. , nan, 15. , nan],
[ nan, 6. , nan, nan, 9. , nan]], dtype=float32)