使此C数组处理代码更加python(甚至numpy)

使此C数组处理代码更加python(甚至numpy),python,c,arrays,numpy,vectorization,Python,C,Arrays,Numpy,Vectorization,我试图了解python(最终还有numpy)惊人的列表处理能力。我正在把我写的一些C代码转换成python 我有一个文本数据文件,其中第一行是标题,然后每一个奇数行是我的输入数据,每一个偶数行是我的输出数据。所有数据空间都是分开的。我非常高兴,我设法使用嵌套列表理解将所有数据读入列表。太棒了 with open('data.txt', 'r') as f: # get all lines as a list of strings lines = list(f) # co

我试图了解python(最终还有numpy)惊人的列表处理能力。我正在把我写的一些C代码转换成python

我有一个文本数据文件,其中第一行是标题,然后每一个奇数行是我的输入数据,每一个偶数行是我的输出数据。所有数据空间都是分开的。我非常高兴,我设法使用嵌套列表理解将所有数据读入列表。太棒了

with open('data.txt', 'r') as f:
    # get all lines as a list of strings
    lines = list(f)

    # convert header row to list of ints and get info
    header = map(int, lines[0].split(' '))
    num_samples = header[0]
    input_dim = header[1]
    output_dim = header[2]
    del header    

    # bad ass list comprehensions 
    inputs = [[float(x) for x in l.split()] for l in lines[1::2]]
    outputs = [[float(x) for x in l.split()] for l in lines[2::2]]
    del x, l, lines
然后我想生成一个新的列表,其中每个元素都是相应输入输出对的函数。我不知道如何使用任何特定于python的优化来实现这一点。这里是C风格的python:

# calculate position
pos_list = [];
pos_y = 0
for i in range(num_samples):
    pantilt = outputs[i];
    target = inputs[i];

    if(pantilt[0] > 90):
        pantilt[0] -=180
        pantilt[1] *= -1
    elif pantilt[0] < -90:
        pantilt[0] += 180
        pantilt[1] *= -1

    tan_pan = math.tan(math.radians(pantilt[0]))
    tan_tilt = math.tan(math.radians(pantilt[1]))

    pos = [0, pos_y, 0]
    pos[2] = tan_tilt * (target[1] - pos[1]) / math.sqrt(tan_pan * tan_pan + 1)
    pos[0] = pos[2] * tan_pan
    pos[0] += target[0]
    pos[2] += target[2]
    pos_list.append(pos)
del pantilt, target, tan_pan, tan_tilt, pos, pos_y
#计算位置
位置列表=[];
位置y=0
对于范围内的i(num_样本):
pantilt=输出[i];
目标=输入[i];
如果(pantilt[0]>90):
pantilt[0]=180
pantilt[1]*=-1
elif pantilt[0]<-90:
pantilt[0]+=180
pantilt[1]*=-1
tan_pan=math.tan(math.radians(pantilt[0]))
tan_tilt=math.tan(数学弧度(pantilt[1]))
位置=[0,位置y,0]
位置[2]=tan_-tilt*(目标[1]-pos[1])/math.sqrt(tan_-pan*tan_-pan+1)
位置[0]=位置[2]*tan_pan
位置[0]+=目标[0]
位置[2]+=目标[2]
位置列表追加(位置)
三角帆,目标,三角帆,三角帆,位置,位置y
我试图用理解力或地图来做这件事,但不知道如何:

  • 从pos_列表数组的每个元素的两个不同列表(输入和输出)中进行绘制
  • 将算法主体放在理解中。它必须是一个单独的函数,还是有一种使用lambdas的时髦方式
  • 有没有可能做到这一点,根本没有循环,只是把它放在numpy中,然后将整个事情矢量化

假设您将文件读入一个列表,如下所示:

lines = open('data.txt', 'r').readlines()
标题如下:

lines[0]
偶数行是:

even = lines[1:][::2] 
odd = lines[2:][::2]
奇数行是:

even = lines[1:][::2] 
odd = lines[2:][::2]
现在,您可以使用以下两个列表创建一个列表:

itertools.izip(even, odd)

这是一种类似thingy的列表(你可以在它上面循环,或者在它周围写
list(…)
,使它成为一个真正的列表),它的每个条目都是一对输入输出数据。

如果有人偶然发现了相同的问题,根据Ami的建议,这里有四种变体(函数do1、do1b、do2、do3)

对于那些好奇的人来说,这里有一些基准(我有大约1000对输入输出数据。可能随着数据的急剧增加,基准的变化会更大)

  • %timeit do3()-100个循环,每个循环最好3:2.72毫秒
  • %timeit do2()-100个循环,每个循环的最佳时间为3:2.73毫秒
  • %timeit do1b()-100个循环,每个循环最好3:2.74毫秒
  • %timeit do1()-100个循环,每个循环最好3:2.67毫秒

def load_文件(文件名='Sharpy_7.txt'):
全局文件数据、样本数、输入尺寸、输出尺寸
将open(filename,'r')作为f:
#将所有行作为字符串列表获取
文件\数据=列表(f)
#将标题行转换为整数列表并获取信息
header=map(int,文件\数据[0]。拆分(“”))
num_samples=标题[0]
输入尺寸=标题[1]
输出尺寸=标题[2]
f、 关闭()
def calc_位置2(d):
目标=d[0]
pantilt=d[1]
如果(pantilt[0]>90):
pantilt[0]=180
pantilt[1]*=-1
elif pantilt[0]<-90:
pantilt[0]+=180
pantilt[1]*=-1
tan_pan=math.tan(math.radians(pantilt[0]))
tan_tilt=math.tan(数学弧度(pantilt[1]))
位置=[0,0,0]
位置[2]=tan_-tilt*(目标[1]-pos[1])/math.sqrt(tan_-pan*tan_-pan+1)
位置[0]=位置[2]*tan_pan
位置[0]+=目标[0]
位置[2]+=目标[2]
返回位置
def calc_位置(目标、仪表盘):
如果(pantilt[0]>90):
pantilt[0]=180
pantilt[1]*=-1
elif pantilt[0]<-90:
pantilt[0]+=180
pantilt[1]*=-1
tan_pan=math.tan(math.radians(pantilt[0]))
tan_tilt=math.tan(数学弧度(pantilt[1]))
位置=[0,0,0]
位置[2]=tan_-tilt*(目标[1]-pos[1])/math.sqrt(tan_-pan*tan_-pan+1)
位置[0]=位置[2]*tan_pan
位置[0]+=目标[0]
位置[2]+=目标[2]
返回位置
def calc_stats():
全球位置阵列、位置平均值、位置标准
位置数组=np.asarray(位置列表)
位置平均值=np.平均值(位置数组,0)
pos_std=np.std(pos_数组,0)
#在itertools.izip上映射
def do3():
全球位置列表
#糟糕的列表理解
target_list=[[float(x)for x in l.split()]for l in file_data[1::2]]
pantilt_list=[[float(x)代表l中的x.split()]代表l中的文件_数据[2::2]]
#计算位置
位置列表=映射(计算位置2,itertools.izip(目标列表,pantilt列表))
#列出对itertools.izip的理解
def do2():
全球位置列表
#糟糕的列表理解
target_list=[[float(x)for x in l.split()]for l in file_data[1::2]]
pantilt_list=[[float(x)代表l中的x.split()]代表l中的文件_数据[2::2]]
#计算位置
pos_list=[itertools.izip(target_list,pantilt_list)中d的计算位置(d[0],d[1])]
#带函数调用的for循环
def do1b():
全球位置列表
#糟糕的列表理解
target_list=[[float(x)for x in l.split()]for l in file_data[1::2]]
pantilt_list=[[float(x)代表l中的x.split()]代表l中的文件_数据[2::2]]
#计算位置
位置列表=[];
对于范围内的i(num_样本):
pos\u list.append(计算pos(目标列表[i],pantilt列表[i]))
#带展开算法的for循环
def do1():
全球位置列表
#糟糕的列表理解
target_list=[[float(x)for x in l.split()]for l in file_data[1::2]]
pantilt_list=[[float(x)代表l中的x.split()]代表l中的文件_数据[2::2]]
#计算位置
位置列表=[];
对于范围内的i(num_样本):
pantilt=pantilt_列表[i];
target=target_list[i];
如果(pantilt[0]>90):
pantilt[0]=180
pantilt[1]*=-1
elif pantilt[0
In [415]: # Parameters and setup input arrays
     ...: num_samples = 1000
     ...: outputs = np.random.randint(-180,180,(num_samples,5))
     ...: inputs = np.random.rand(num_samples,6)
     ...: pos_y = 3.4
     ...: 

In [416]: %timeit original(inputs,outputs,pos_y)
100 loops, best of 3: 2.44 ms per loop

In [417]: %timeit mask_vectorized(inputs,outputs,pos_y)
10000 loops, best of 3: 181 µs per loop