【问题标题】:Splitting a large ndarray拆分一个大的ndarray
【发布时间】:2015-09-14 17:25:48
【问题描述】:

我对 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 个 epoch 的信号。我尝试使用以下代码分别打开新文件,但生成的文本文件仅显示以下输出:

代码:

for i in range(32): 
    sat = obss[:, i] 
    open(((("sv{0}").format(sat)),'w').writelines(sat)) 

在文本文件中输出:

ø ø ø ø ø ø ø 

所以很明显,我忽略的数组操作有问题。从read_data函数调用read_data_chunk函数:

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' object has no attribute 'ndim'

【问题讨论】:

  • 有一个StackExchange GIS site - 那边的人可能已经解决了这个问题。同时,如果您能向我们展示一个obss 的示例,其中包含两到三颗卫星的几行,将会有所帮助。
  • @wwii - GPS != GIS。我猜 OP 想要做详细的大地测量工作(例如板块运动等)。无论哪种方式,这都不是与 GIS 相关的问题。无论如何,你说得对,多一点示例数据会有很大帮助。
  • @JoeKington - 我想那里有熟悉 RINEX、大地测量学、GPS、geowhatever 的人......他们经常使用 Python 来解决他们的问题。也就是说,我确实找到了一个有趣的SO question 并回答了。
  • 在我看来它们已经“分裂”了:只需沿轴 1 索引。如果您想循环通过 32 颗卫星或其他东西,您可以将其作为第一个轴:y = np.rollaxis(obss, 1),那么y.shape(32, 10000, 7),如果你对y[0] 做任何事情,它将成为第一颗卫星,或者如果你想循环通过每颗卫星,for sat in y: ... 将一次给你一颗卫星。
  • 现在查看您的更新,@pymat。您以几种方式粘贴了内容(似乎重复),但我认为您拥有的最后一件事(pd.Panel)是最好的继续方式。而且您不需要滚动它,因为卫星轴已经是第一个轴:尝试obs_data_chunks[0],您将拥有您的第一个卫星。

标签: python numpy pandas split gps


【解决方案1】:

这取决于您究竟想对这 32 个卫星子集做什么。据我所知,你目前拥有obss,形状为(10000, 32, 7),你已经以某种方式“分裂”了它。以下是访问它们的方法:

  1. 沿“卫星”维度切片,即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. 如果你发现你主要是通过卫星索引,你可以用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. 如果您想循环遍历卫星,就像在 y = np.split(obss) 示例中那样,更简单的方法是:

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

    或者,如果你为sats滚动轴,你可以这样做:

    sats = np.rollaxis(obss, 1)
    for sat in sats:
        ...
    
  4. 最后,如果你真的想要卫星列表,你可以这样做

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

【讨论】:

  • 嗨@pymat,您可以在您的问题中发布该信息作为更新吗?它很难阅读,也无法从 cmets 复制。如果您这样做,我将很乐意阅读并帮助您。在这里再评论一次,让我知道你已经做到了。 (您可以在评论中输入@askewchan 来引起我的注意)。
  • 刚刚添加。干杯。 @askewchan
猜你喜欢
  • 2020-10-04
  • 1970-01-01
  • 1970-01-01
  • 2022-10-04
  • 2014-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-04
相关资源
最近更新 更多