将一个大的ndarray分割

3

我对Python和Pandas、Numpy都比较陌生。我正在尝试格式化一个GPS RINEX文件,使其被分为卫星(总共32个)。每个文件(即卫星)应按时刻(每30秒)进行格式化,其中每个信号的数据(总共7个)应显示在相应的列中。例如:

SV1
2014-11-07 00:00:00 L1    L2    P1    P2    C1    S1    S2 
2014-11-07 00:00:30 L1    L2    P1    P2    C1    S1    S2 
2014-11-07 00:00:30 L1    L2    P1    P2    C1    S1    S2

我正在处理的代码,特别是函数部分,是:
def read_data_chunk(self, RINEXfile, CHUNK_SIZE = 10000):
    obss = np.empty((CHUNK_SIZE, TOTAL_SATS, len(self.obs_types)), dtype=np.float64) * np.NaN
    llis = np.zeros((CHUNK_SIZE, TOTAL_SATS, len(self.obs_types)), dtype=np.uint8)
    signal_strengths = np.zeros((CHUNK_SIZE, TOTAL_SATS, len(self.obs_types)), dtype=np.uint8)
    epochs = np.zeros(CHUNK_SIZE, dtype='datetime64[us]')
    flags = np.zeros(CHUNK_SIZE, dtype=np.uint8)

    i = 0
    while True:
        hdr = self.read_epoch_header(RINEXfile)
        #print hdr
        if hdr is None:
            break
        epoch, flags[i], sats = hdr
        epochs[i] = np.datetime64(epoch)
        sat_map = np.ones(len(sats)) * -1
        for n, sat in enumerate(sats):
            if sat[0] == 'G':
                sat_map[n] = int(sat[1:]) - 1
        obss[i], llis[i], signal_strengths[i] = self.read_obs(RINEXfile, len(sats), sat_map)
        i += 1
        if i >= CHUNK_SIZE:
            break

    print "obss.ndim: {0}".format(obss.ndim)
    print "obss.shape: {0}" .format(obss.shape)
    print "obss.size: {0}".format(obss.size)
    print "obss.dtype: {0}".format(obss.dtype)
    print "obss.itemsize: {0}".format(obss.itemsize)
    print "obss: {0}".format(obss)

    y = np.split(obss, 32, 1)
    print "y.ndim: {0}".format(y[3].ndim)
    print "y.shape: {0}" .format(y[3].shape)
    print "y.size: {0}".format(y[3].size)
    print "y_0: {0}".format(y[3])

    return obss[:i], llis[:i], signal_strengths[:i], epochs[:i], flags[:i]

这些打印语句只是为了理解涉及的维度,其结果如下:

obss.ndim: 3
obss.shape: (10000L, 32L, 7L)
obss.size: 2240000
obss.dtype: float64
obss.itemsize: 8
y.ndim: 3
y.shape: (10000L, 1L, 7L)
y.size: 70000

我遇到的具体问题是如何精确地操作,以便将数组分成其后续的32个部分(即卫星)。以下是迄今为止的输出示例:

sats = np.rollaxis(obss, 1, 0) 
sat = sats[5] #sv6 
sat.shape: (10000L, 7L) 
sat.ndim: 2 
sat.size: 70000 
sat.dtype: float64 
sat.item
size: 8 
sat: [[ -7.28308440e+06 -5.66279406e+06 2.38582902e+07 ..., 2.38582906e+07 4.70000000e+01 4.20000000e+01] [ -7.32362993e+06 -5.69438797e+06 2.38505736e+07 ..., 2.38505742e+07 4.70000000e+01 4.20000000e+01] [ -7.36367675e+06 -5.72559325e+06 2.38429526e+07 ..., 2.38429528e+07 4.60000000e+01 4.20000000e+01] 

上述输出是针对第6颗卫星(“sat”)的,并显示了前3个历元的信号。我尝试了下面的代码来单独打开新文件,但生成的文本文件只显示了以下输出:
代码:
for i in range(32): 
    sat = obss[:, i] 
    open(((("sv{0}").format(sat)),'w').writelines(sat)) 

输出到文本文件:

ø ø ø ø ø ø ø 

显然,我在操作数组时忽略了某些问题。函数read_data_chunk由函数read_data调用:

def read_data(self, RINEXfile): 
    obs_data_chunks = [] 
    while True: 
        obss, _, _, epochs, _ = self.read_data_chunk(RINEXfile) 
        if obss.shape[0] == 0: 
            break 

        obs_data_chunks.append(pd.Panel( np.rollaxis(obss, 1, 0), items=['G%02d' % d for d in range(1, 33)], major_axis=epochs,minor_axis=self.obs_types).dropna(axis=0, how='all').dropna(axis=2, how='all'))   

    print "obs_data_chunks: {0}".format(obs_data_chunks) 
    self.data = pd.concat(obs_data_chunks, axis=1) 

下一步我尝试的是上面代码中的操作,因为我认为这个数组可能是需要被操作的正确对象。最终的打印语句:
obs_data_chunks: [<class 'pandas.core.panel.Panel'> 
Dimensions: 32 (items) x 2880 (major_axis) x 7 (minor_axis) 
Items axis: G01 to G32 
Major_axis axis: 2014-04-27 00:00:00 to 2014-04-27 23:59:30 
Minor_axis axis: L1 to S2] 

我尝试弄清楚如何使用以下内容处理obs_data_chunks数组:

odc = np.rollaxis(obs_data_chunks, 1) 
odc_temp = odc[5]   

但是收到了一个错误:AttributeError: 'list'对象没有属性 'ndim'


这里有一个StackExchange GIS网站 - 那里可能已经有人解决了这个问题。同时,如果您能展示一下包含两三颗卫星的obss示例,那将会很有帮助。 - wwii
@wwii - GPS ≠ GIS。我猜测原帖想要进行详细的大地测量工作(如板块运动等)。不管怎样,这不是一个与GIS相关的问题。无论如何,你说得很对,提供更多的示例数据会非常有帮助。 - Joe Kington
1
@JoeKington - 我想那里有一些熟悉RINEX、大地测量学、GPS、地理等领域的人,他们经常使用Python来解决问题。话虽如此,我还是发现了一个有趣的SO问题和答案。 - wwii
看起来它们已经被“分割”了:只需沿轴1进行索引。如果您想循环遍历32颗卫星之类的东西,可以将其作为第一个轴:y = np.rollaxis(obss, 1),然后y.shape(32, 10000, 7),如果您对y[0]做任何操作,它将是第一颗卫星,或者如果您想循环遍历每个卫星,for sat in y: ...将为您提供一个卫星。 - askewchan
看了你的更新,@pymat。你在几个地方都复制粘贴了一些东西(似乎有点重复),但我认为你最后的那个pd.Panel是继续进行的最佳方式。而且你不需要滚动它,因为卫星轴已经是第一个轴:尝试使用obs_data_chunks[0],你将得到第一个卫星。 - askewchan
1个回答

1
这取决于您想如何处理这32个卫星子集。据我所知,您目前拥有的obss,形状为(10000, 32, 7),已经以一种方式进行了“分割”。以下是如何访问它们的方法:
  1. Slice along the 'satellite' dimension, which is axis=1:

    sat = obss[:, 0]  # all the data for satellite 0, with shape (10000, 7)
    sat = obss[:, i]  # for any i from 0 through 31.
    sats = obss[:, :3] # the first three satellites
    
  2. If you find that you are mainly indexing by satellite, you can move its axis to the front with np.rollaxis:

    sats = np.rollaxis(obss, 1)
    sats.shape
    # (32, 10000, 7)
    sat = sats[i]  # satellite i, equivalent to obss[:, i]
    sat = sats[:3] # first three satellites
    
  3. If you want to loop through the satellites, as you would in your y = np.split(obss) example, an easier way to do that is:

    for i in range(32):
        sat = obss[:, i]
        ...
    

    or, if you roll the axis for sats, you can just do:

    sats = np.rollaxis(obss, 1)
    for sat in sats:
        ...
    
  4. Finally, if you really want a list of the satellites, you can do

    sats = np.rollaxis(obss, 1)
    satlist = list(sats)
    

嗨,@pymat,你能把那些信息作为更新发布到你的问题中吗?从评论中阅读很困难,也无法复制。如果你这样做了,我会很高兴阅读并帮助你解决问题。完成后再在这里留言告诉我一声(你可以在评论中输入“@askewchan”来引起我的注意)。 - askewchan
刚刚添加了它。干杯。@askewchan - pymat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接