【问题标题】:Handle Fortran Character Arrays from Python with F2PY使用 F2PY 从 Python 处理 Fortran 字符数组
【发布时间】:2016-10-05 00:49:18
【问题描述】:

我有一个用 F2PY 封装的旧版 Fortran 库。但是,我不知道如何从 Python 中正确读取声明为模块数据的字符数组。数据数据通过,但数组以一种难以辨认的方式转置。如何让 Numpy 正确处理我的数组?如果它们的顺序清晰,我会对二维字符数组感到满意。

在 Fortran 中声明和填充字符数组,如下所示:

module plot_mod
    implicit none

    CHARACTER*4, JSP(39)

    ...

    JSP = (/ &
      'SF ',   'WF ',   'GF ',   'AF ',   'RF ',   'SS ',   'NF ', &
      'YC ',   'IC ',   'ES ',   'LP ',   'JP ',   'SP ',   'WP ', &
      'PP ',   'DF ',   'RW ',   'RC ',   'WH ',   'MH ',   'BM ', &
      'RA ',   'WA ',   'PB ',   'GC ',   'AS ',   'CW ',   'WO ', &
      'WJ ',   'LL ',   'WB ',   'KP ',   'PY ',   'DG ',   'HT ', &
      'CH ',   'WI ',   '   ',   'OT '/)

end module plot_mod

在 Python 2.7(numpy 的以前版本)中,我可以这样做:

x = numpy.frombuffer(fvslib.plot_mod.jsp.data, numpy.dtype('a4'))

但现在 Python (3.4.4) 和 Numpy (1.10.4) 出现错误,BufferError: memoryview: underlying buffer is not C-contiguous

我知道我应该能够让 Numpy 通过重塑或使用跨步技巧来为我处理这个问题,但我似乎无法弄清楚。该数组被报告为 F 连续,所以至少这看起来是正确的。

如果我只是打印数组,它看起来像这样:

array([[b'S', b' ', b' ', b'L'],
   [b'F', b'L', b' ', b' '],
   [b' ', b'P', b'B', b' '],
   [b' ', b' ', b'M', b'W'],
   [b'W', b' ', b' ', b'B'],
   [b'F', b'J', b' ', b' '],
   [b' ', b'P', b'R', b' '],
   [b' ', b' ', b'A', b'K'],
   [b'G', b' ', b' ', b'P'],
   [b'F', b'S', b' ', b' '],
   [b' ', b'P', b'W', b' '],
   [b' ', b' ', b'A', b'P'],
   [b'A', b' ', b' ', b'Y'],
   [b'F', b'W', b' ', b' '],
   [b' ', b'P', b'P', b' '],
   [b' ', b' ', b'B', b'D'],
   [b'R', b' ', b' ', b'G'],
   [b'F', b'P', b' ', b' '],
   [b' ', b'P', b'G', b' '],
   [b' ', b' ', b'C', b'H'],
   [b'S', b' ', b' ', b'T'],
   [b'S', b'D', b' ', b' '],
   [b' ', b'F', b'A', b' '],
   [b' ', b' ', b'S', b'C'],
   [b'N', b' ', b' ', b'H'],
   [b'F', b'R', b' ', b' '],
   [b' ', b'W', b'C', b' '],
   [b' ', b' ', b'W', b'W'],
   [b'Y', b' ', b' ', b'I'],
   [b'C', b'R', b' ', b' '],
   [b' ', b'C', b'W', b' '],
   [b' ', b' ', b'O', b' '],
   [b'I', b' ', b' ', b' '],
   [b'C', b'W', b' ', b' '],
   [b' ', b'H', b'W', b' '],
   [b' ', b' ', b'J', b'O'],
   [b'E', b' ', b' ', b'T'],
   [b'S', b'M', b' ', b' '],
   [b' ', b'H', b'L', b' ']],
  dtype='|S1')

我想要这样的数组:

[['SF ']
, ['WF ']
, ['GF ']
, ['AF ']
, ['RF ']
, ['SS ']
, ['NF ']
, ['YC ']
, ['IC ']
, ['ES ']
, ['LP ']
, ['JP ']
, ['SP ']
, ['WP ']
, ['PP ']
, ['DF ']
, ['RW ']
, ['RC ']
, ['WH ']
, ['MH ']
, ['BM ']
, ['RA ']
, ['WA ']
, ['PB ']
, ['GC ']
, ['AS ']
, ['CW ']
, ['WO ']
, ['WJ ']
, ['LL ']
, ['WB ']
, ['KP ']
, ['PY ']
, ['DG ']
, ['HT ']
, ['CH ']
, ['WI ']
, ['   ']
, ['OT ']]

【问题讨论】:

    标签: python numpy fortran


    【解决方案1】:

    我没有尝试在你的模块上运行 f2py,但是如果我定义了你显示的数组:

    In [11]: s = array([[b'S', b' ', b' ', b'L'],
        ...:    [b'F', b'L', b' ', b' '],
        ...:    [b' ', b'P', b'B', b' '],
        ...:    [b' ', b' ', b'M', b'W'],
        ...:    [b'W', b' ', b' ', b'B'],
        ...:    [b'F', b'J', b' ', b' '],
        ...:    [b' ', b'P', b'R', b' '],
        ...:    [b' ', b' ', b'A', b'K'],
        ...:    [b'G', b' ', b' ', b'P'],
        ...:    [b'F', b'S', b' ', b' '],
        ...:    [b' ', b'P', b'W', b' '],
        ...:    [b' ', b' ', b'A', b'P'],
        ...:    [b'A', b' ', b' ', b'Y'],
        ...:    [b'F', b'W', b' ', b' '],
        ...:    [b' ', b'P', b'P', b' '],
        ...:    [b' ', b' ', b'B', b'D'],
        ...:    [b'R', b' ', b' ', b'G'],
        ...:    [b'F', b'P', b' ', b' '],
        ...:    [b' ', b'P', b'G', b' '],
        ...:    [b' ', b' ', b'C', b'H'],
        ...:    [b'S', b' ', b' ', b'T'],
        ...:    [b'S', b'D', b' ', b' '],
        ...:    [b' ', b'F', b'A', b' '],
        ...:    [b' ', b' ', b'S', b'C'],
        ...:    [b'N', b' ', b' ', b'H'],
        ...:    [b'F', b'R', b' ', b' '],
        ...:    [b' ', b'W', b'C', b' '],
        ...:    [b' ', b' ', b'W', b'W'],
        ...:    [b'Y', b' ', b' ', b'I'],
        ...:    [b'C', b'R', b' ', b' '],
        ...:    [b' ', b'C', b'W', b' '],
        ...:    [b' ', b' ', b'O', b' '],
        ...:    [b'I', b' ', b' ', b' '],
        ...:    [b'C', b'W', b' ', b' '],
        ...:    [b' ', b'H', b'W', b' '],
        ...:    [b' ', b' ', b'J', b'O'],
        ...:    [b'E', b' ', b' ', b'T'],
        ...:    [b'S', b'M', b' ', b' '],
        ...:    [b' ', b'H', b'L', b' ']],
        ...:   dtype='|S1')
    

    我可以得到一个看起来像你想要的数组:

    In [12]: s.T.reshape(-1, 4).view('S4')
    Out[12]: 
    array([[b'SF  '],
           [b'WF  '],
           [b'GF  '],
           [b'AF  '],
           [b'RF  '],
           [b'SS  '],
           [b'NF  '],
           [b'YC  '],
           [b'IC  '],
           [b'ES  '],
           [b'LP  '],
           [b'JP  '],
           [b'SP  '],
           [b'WP  '],
           [b'PP  '],
           [b'DF  '],
           [b'RW  '],
           [b'RC  '],
           [b'WH  '],
           [b'MH  '],
           [b'BM  '],
           [b'RA  '],
           [b'WA  '],
           [b'PB  '],
           [b'GC  '],
           [b'AS  '],
           [b'CW  '],
           [b'WO  '],
           [b'WJ  '],
           [b'LL  '],
           [b'WB  '],
           [b'KP  '],
           [b'PY  '],
           [b'DG  '],
           [b'HT  '],
           [b'CH  '],
           [b'WI  '],
           [b'    '],
           [b'OT  ']], 
          dtype='|S4')
    

    请注意,数据类型为'S4',以匹配声明的 Fortran 数组大小。

    该结果留下了一个微不足道的第二维,因此您可能希望将其转换为一维数组,例如

    In [22]: s.T.reshape(-1, 4).view('S4')[:,0]
    Out[22]: 
    array([b'SF  ', b'WF  ', b'GF  ', b'AF  ', b'RF  ', b'SS  ', b'NF  ',
           b'YC  ', b'IC  ', b'ES  ', b'LP  ', b'JP  ', b'SP  ', b'WP  ',
           b'PP  ', b'DF  ', b'RW  ', b'RC  ', b'WH  ', b'MH  ', b'BM  ',
           b'RA  ', b'WA  ', b'PB  ', b'GC  ', b'AS  ', b'CW  ', b'WO  ',
           b'WJ  ', b'LL  ', b'WB  ', b'KP  ', b'PY  ', b'DG  ', b'HT  ',
           b'CH  ', b'WI  ', b'    ', b'OT  '], 
          dtype='|S4')
    

    【讨论】:

    • 完美。转置是我错过的关键。发布后不久,我想出了如何使用 stride_tricks 模块进行操作,但恕我直言,这要好得多。
    【解决方案2】:

    为了完整起见,我将包含此替代解决方案。结果与@Warren Weckesser 相同,但需要额外导入。

    from numpy.lib import stride_tricks
    
    spp = stride_tricks.as_strided(jsp, strides=(jsp.shape[1],1))
    
    # View as S4 and strip whitespace
    spp = np.char.strip(spp.view('S4'))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-13
      • 1970-01-01
      • 1970-01-01
      • 2017-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多