【导读】Numpy是python数据分析和科学计算的核心软件包。 上次介绍了numpy的一些基础操作。例如如何创建一个array,如何提取array元素,重塑(reshape)数组,生成随机数(random)等,在这一部分,专知成员Fan将详细介绍numpy的高级功能,这些功能对于数据分析和操作非常重要。
Numpy教程第1部分可以参见专知公众号:
▌一、如何使用np.where获得满足给定条件的索引位置?
1、有时候我们不仅仅需要知道array中满足条件的元素是什么,也需要知道满足条件的元素在array中的索引:
import numpy as np
arr_rand = np.array([8, 8, 3, 7, 7, 0, 4, 2, 5, 2])
print("Array: ", arr_rand)
# Positions where value > 5
index_gt5 = np.where(arr_rand > 5)
print("Positions where value > 5: ", index_gt5)
#> Array: [8 8 3 7 7 0 4 2 5 2]
#> Positions where value > 5: (array([0, 1, 3, 4]),)
2、对于提取出的索引,可以利用数组的take方法取出符合条件的元素:
arr_rand.take(index_gt5)
#> array([[8, 8, 7, 7]])
3、np.where可以在括号里添加两个参数,a和b,当条件满足时,元素改为a,不满足时改为b
np.where(arr_rand > 5, 'gt5', 'le5')
#> array(['gt5', 'gt5', 'le5', 'gt5', 'gt5', 'le5', 'le5', 'le5', 'le5', 'le5'],
dtype='<U3')
4、找到数组中最大值(argmax)与最小值(argmin)的索引
print('Position of max value: ', np.argmax(arr_rand))
#> Position of max value: 0
▌二、如何导入和导出.csv的数据?
1、np.genfromtxt可以导入web URLs的数据,并且可以解决缺少值,多个分隔符,以及处理不规则数量的列等问题。
#关闭科学计数法
np.set_printoptions(suppress=True)
# Import data from csv file url
path = 'https://raw.githubusercontent.com/selva86/datasets/master/Auto.csv'
data = np.genfromtxt(path, delimiter=',', skip_header=1, filling_values=-999, dtype='float')
data[:3] # see first 3 rows
#> array([[18.,8.,307.,130.,3504.,12.,70.,#> 1.,-999. ],
#>[15.,8.,350.,165.,3693.,11.5,70.,#>1.,-999. ],
#>[18.,8.,318.,150.,3436.,11.,70.,#>1.,-999.]])
最后一列输出都为-999,因为array需要数据类型一样,对于最后一列的文本信息,它不知道该怎么去转化。
2、那么如何处理包含数字和文本列的数据集呢?
正如在上节所提到的,您可以将dtype设为object,当然这里你可以设为None
#data2 = np.genfromtxt(path, delimiter=',', skip_header=1, dtype='object')
data2 = np.genfromtxt(path, delimiter=',', skip_header=1, dtype=None)
data2[:3] # see first 3 rows
#> array([( 18., 8, 307., 130, 3504, 12. , 70, 1, b'
"chevrolet chevelle malibu"'),
#> ( 15., 8, 350., 165, 3693, 11.5, 70, 1,
b'"buick skylark 320"'),
#> ( 18., 8, 318., 150, 3436, 11. , 70, 1,
b'"plymouth satellite"')],
#> dtype=[('f0', '<f8'), ('f1', '<i8'), ('f2', '<f8'),
('f3', '<i8'), ('f4', '<i8'),
('f5', '<f8'), ('f6', '<i8'), ('f7', '<i8'), ('f8', 'S38')])
3、将arary导出为.csv文件?
np.savetxt("out.csv", data, delimiter=",")
▌三、如何保存并加载numpy对象?
在某些情况下,我们希望将大型转换后的numpy数组保存到磁盘并直接将其加载回控制台,而无需重新运行数据转换代码。Numpy为此提供了.npy和.npz文件类型。
1、如果你想存储一个ndarray对象,用np.save存为.npy,然后用np.load导入。
2、如果你想在一个文件中存储多于1个的ndarray对象,用np.savez存为.npz。
# Save single numpy array object as .npy file
np.save('myarray.npy', arr2d)
# Save multile numy arrays as a .npz file
np.savez('array.npz', arr2d_f, arr2d_b)
3、导出数据
# Load a .npy file
a = np.load('myarray.npy')print(a)
#> [[0 1 2]#> [3 4 5]#> [6 7 8]]
# Load a .npz file
b = np.load('array.npz')print(b.files)
b['arr_0']
#> ['arr_0', 'arr_1']
#> array([[ 0., 1., 2.],
#> [ 3., 4., 5.],
#> [ 6., 7., 8.]])
▌三、如何连接两个numpy数组,列式和行式?
Method 1: np.concatenate
Method 2: np.vstack 和 np.hstack
Method 3: np.r_ 和np.c_
这三种方法输出的结果是一样的。但是np.r_和np.c_都使用方括号来堆栈数组。 但首先,让我创建要并置的数组。
1、让我们垂直堆叠数组:
a = np.zeros([4, 4])
b = np.ones([4, 4])
# Vertical Stack Equivalents (Row wise)
np.concatenate([a, b], axis=0)
np.vstack([a,b])
np.r_[a,b]
#> array([[ 0., 0., 0., 0.],
#> [ 0., 0., 0., 0.],
#> [ 0., 0., 0., 0.],
#> [ 0., 0., 0., 0.],
#> [ 1., 1., 1., 1.],
#> [ 1., 1., 1., 1.],
#> [ 1., 1., 1., 1.],
#> [ 1., 1., 1., 1.]])
2、让我们水平堆叠数组:
np.concatenate([a, b], axis=1)
np.hstack([a,b])
np.c_[a,b]
#> array([[ 0., 0., 0., 0., 1., 1., 1., 1.],
#> [ 0., 0., 0., 0., 1., 1., 1., 1.],
#> [ 0., 0., 0., 0., 1., 1., 1., 1.],
#> [ 0., 0., 0., 0., 1., 1., 1., 1.]])
4、用np.r_把复杂的数据序列创建成一维的array
# Horizontal Stack Equivalents (Coliumn wise)np.r_[[1,2,3], 0, 0, [4,5,6]]
#> array([1, 2, 3, 0, 0, 4, 5, 6])
▌四、如何基于一列或多列对numpy数组进行排序?
arr = np.random.randint(1,6, size=[8, 4])
arr
#> array([[3, 3, 2, 1],
#> [1, 5, 4, 5],
#> [3, 1, 4, 2],
#> [3, 4, 5, 5],
#> [2, 4, 5, 5],
#> [4, 4, 4, 2],
#> [2, 4, 1, 3],
#> [2, 2, 4, 3]])
按列排序:
np.sort(arr, axis=0)
#> array([[1, 1, 1, 1],
#> [2, 2, 2, 2],
#> [2, 3, 4, 2],
#> [2, 4, 4, 3],
#> [3, 4, 4, 3],
#> [3, 4, 4, 5],
#> [3, 4, 5, 5],
#> [4, 5, 5, 5]])
1、如何使用argsort对基于1d的numpy数组进行排序?
np.argsort返回1d数组排序后的索引位置
# Get the index positions that would sort the array
x = np.array([1, 10, 5, 2, 8, 9])
sort_index = np.argsort(x)
print(sort_index)
#> [0 3 2 4 5 1]
这里3表示排序后第二小的数位于原来数组的第四个位置(索引从0开始)
x[sort_index]
#> array([ 1, 2, 5, 8, 9, 10])
2、按照第一列排序,其他列保持不变
arr = np.random.randint(1,6, size=[8, 4])
arr
#> array([[3, 3, 2, 1],
#> [1, 5, 4, 5],
#> [3, 1, 4, 2],
#> [3, 4, 5, 5],
#> [2, 4, 5, 5],
#> [4, 4, 4, 2],
#> [2, 4, 1, 3],
#> [2, 2, 4, 3]])
sorted_index_1stcol = arr[:, 0].argsort()
arr[sorted_index_1stcol]
#> array([[1, 5, 4, 5],
#> [2, 4, 5, 5],
#> [2, 4, 1, 3],
#> [2, 2, 4, 3],
#> [3, 3, 2, 1],
#> [3, 1, 4, 2],
#> [3, 4, 5, 5],
#> [4, 4, 4, 2]])
▌五、对日期进行操作
1、Numpy通过np.datetime64对象实现日期,该对象支持精度直到纳秒。 您可以使用标准的YYYY-MM-DD格式的日期字符串创建一个。
date64 = np.datetime64('2018-02-04 23:10:10')
date64
#> numpy.datetime64('2018-02-04T23:10:10')
#输出日期
dt64 = np.datetime64(date64, 'D')
dt64
#> numpy.datetime64('2018-02-04')
2、给日期增值
默认情况下,是加在天数上。其他情况下需要用np.timedelta64
print('Add 10 days: ', dt64 + 10)
tenminutes = np.timedelta64(10, 'm') # 10 minutes
print('Add 10 minutes: ', dt64 + tenminutes)
3、让我将dt64转换回字符串
np.datetime_as_string(dt64)
#> '2018-02-04'
4、用np.is_busday()来判断某一天是否为工作日
print('Date: ', dt64)
print("Is it a business day?: ", np.is_busday(dt64))
#增加两个工作日,打印离该日期前且最近的工作日
print("Add 2 business days, rolling forward to nearest biz day: ",
np.busday_offset(dt64, 2, roll='forward'))
#增加两个工作日,找出靠后的工作日
print("Add 2 business days, rolling backward to nearest biz day: ",
np.busday_offset(dt64, 2, roll='backward'))
#> Date: 2018-02-04
#> Is it a business day?: False
#> Add 2 business days, rolling forward to nearest biz day: 2018-02-07
#> Add 2 business days, rolling backward to nearest biz day: 2018-02-06
▌六、如何创建日期序列
dates = np.arange(np.datetime64('2018-02-01'),
np.datetime64('2018-02-10'))print(dates)
# 检查一下是否是工作日
np.is_busday(dates)
#> ['2018-02-01' '2018-02-02' '2018-02-03' '2018-02-04' '2018-02-05'
#> '2018-02-06' '2018-02-07' '2018-02-08' '2018-02-09']
array([ True, True, False, False, True, True, True, True, True],
dtype=bool)
▌七、如何将numpy.datetime64转换为datetime.datetime对象?
import datetime
dt = dt64.tolist()
Dt
#> datetime.date(2018, 2, 4)
print('Year: ', dt.year)
print('Day of month: ', dt.day)print('Month of year: ', dt.month)
print('Day of Week: ', dt.weekday()) # Sunday
#> Year: 2018
#> Day of month: 4
#> Month of year: 2
#> Day of Week: 6
▌八、 矢量化 - 使标量函数适用于矢量
1、foo函数(下面会定义)接受一个数字,如果它是“奇数”则将其平方,否则它将它除以2。当你将这个函数应用于标量(单个数字)时,它可以很好地工作,但在应用于array时失败。使用vectorize()后,你可以在array上很好地工作。
# Define a scalar functiondef foo(x):
if x % 2 == 1:
return x**2
else:
return x/2
print('x = 10 returns ', foo(10))
print('x = 11 returns ', foo(11))
#> x = 10 returns 5.0
#> x = 11 returns 121
# Vectorize foo(). Make it work on vectors.
foo_v = np.vectorize(foo, otypes=[float])
print('x = [10, 11, 12] returns ', foo_v([10, 11, 12]))
print('x = [[10, 11, 12], [1, 2, 3]] returns ', foo_v([[10, 11, 12],
[1, 2, 3]]))
#> x = [10, 11, 12] returns [ 5. 121. 6.]
#> x = [[10, 11, 12], [1, 2, 3]] returns [[ 5. 121. 6.]
#> [ 1. 1. 9.]]
2、找出行与列的最大值与最小值
np.random.seed(100)
arr_x = np.random.randint(1,10,size=[4,10])
arr_x
#> array([[9, 9, 4, 8, 8, 1, 5, 3, 6, 3],#>
[3, 3, 2, 1, 9, 5, 1, 7, 3, 5],
#> [2, 6, 4, 5, 5, 4, 8, 2, 2, 8],
#> [8, 1, 3, 4, 3, 6, 9, 2, 1, 8]])
上面是随机生成一个4*10的数组
def max_minus_min(x):
return np.max(x) - np.min(x)
# Apply along the rows
print('Row wise: ', np.apply_along_axis(max_minus_min, 1, arr=arr_x))
# Apply along the columns
print('Column wise: ', np.apply_along_axis(max_minus_min, 0, arr=arr_x))
#> Row wise: [8 8 6 8]
#> Column wise: [7 8 2 7 6 5 8 5 5 5]
3、searchsorted - 查找要插入的位置,以便数组保持排序状态
x = np.arange(10)
print('Where should 5 be inserted?: ', np.searchsorted(x, 5))
print('Where should 5 be inserted (right)?: ', np.searchsorted(x, 5,
side='right'))
#> Where should 5 be inserted?: 5
#> Where should 5 be inserted (right)?: 6
▌九、如何给一个数组增加维度?
有时您可能想将一维数组转换为二维数组(如电子表格)而不添加任何其他数据。
# Create a 1D array
x = np.arange(5)
print('Original array: ', x)
# Introduce a new column axis
x_col = x[:, np.newaxis]
print('x_col shape: ', x_col.shape)
print(x_col)
# Introduce a new row axis
x_row = x[np.newaxis, :]
print('x_row shape: ', x_row.shape)
print(x_row)
#> Original array: [0 1 2 3 4]
#> x_col shape: (5, 1)
#> [[0]
#> [1]
#> [2]
#> [3]
#> [4]]
#> x_row shape: (1, 5)
#> [[0 1 2 3 4]]
▌十、其他一些有用的功能
1、Digitize
用于查找x中的元素在bins的哪个范围,下例中三个范围为0-3;3-6;6-9;分别代表1,2,3,(其中范围取左边界,右边为开边界,即0-3包含0、1、2)
x = np.arange(10)
x
#>array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
bins = np.array([0, 3, 6, 9])
# Get bin allotments
np.digitize(x, bins)
#> array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4])
2、clip
限定范围,大于或小于边界的点都用边界的值代替
np.clip(x, 3, 8)
#> array([3, 3, 3, 3, 4, 5, 6, 7, 8, 8])
3、Histogram and Bincount
histogram()和bincount()都给出了出现的频率。 但有一定的差异。前者只统计出现的元素的频率,而后者计算最小值和最大值之间同类型所有元素的频率,包括没有出现的元素的概率。具体看下面的例子:
x = np.array([1,1,2,2,2,4,4,5,6,6,6]) # doesn't need to be sorted
np.bincount(x) # 0 occurs 0 times, 1 occurs 2 times, 2 occurs thrice.......
#> array([0, 2, 3, 0, 2, 1, 3], dtype=int64)
counts, bins = np.histogram(x, [0, 2, 4, 6, 8])
print('Counts: ', counts)
print('Bins: ', bins)
#> Counts: [2 3 3 3]
#> Bins: [0 2 4 6 8]
总结:numpy常伴python的使用,numpy的一些用法在数据处理方面非常重要。
1、找出满足条件的值的索引(找到索引就找到了值)。
2、数组的排序(不管是整体排序,还是按列排序),一个排序好的数组某些时候有利于直接使用。
3、数组的拼接(数组之间进行拼接,横向或者纵向)。
4、矢量化 - 使标量函数适用于矢量
5、对于数据集的读入读出(当然方法不唯一)
参考链接:
https://www.machinelearningplus.com/numpy-tutorial-python-part2/
-END-
专 · 知
人工智能领域主题知识资料查看获取:【专知荟萃】人工智能领域26个主题知识资料全集(入门/进阶/论文/综述/视频/专家等)
请PC登录www.zhuanzhi.ai或者点击阅读原文,注册登录专知,获取更多AI知识资料!
请扫一扫如下二维码关注我们的公众号,获取人工智能的专业知识!
请加专知小助手微信(Rancho_Fang),加入专知主题人工智能群交流!加入专知主题群(请备注主题类型:AI、NLP、CV、 KG等)交流~
点击“阅读原文”,使用专知