Как Numpy обрабатывает файлы данных со значениями неопределенности, например, 0,6499(6)?

Вот фрагмент большого набора данных, с которым я работаю:

# p*  T*     P*         U*          P*_cs    U*_cs  Steps  dt*
0.1   6.0    0.6499(6) -0.478(2)    0.6525  -0.452  30000  0.002
0.2   6.0    1.442(1)  -0.942(2)    1.452   -0.890  30000  0.002
0.3   6.0    2.465(3)  -1.376(1)    2.489   -1.298  30000  0.002
0.4   6.0    3.838(5)  -1.785(3)    3.880   -1.681  20000  0.002
0.5   6.0    5.77(1)   -2.131(3)    5.84    -2.000  20000  0.002
0.6   6.0    8.51(2)   -2.382(5)    8.60    -2.225  20000  0.002
0.7   6.0   12.43(2)   -2.501(4)   12.56    -2.318  20000  0.002
0.8   6.0   18.05(2)   -2.416(4)   18.22    -2.207  20000  0.002
0.9   6.0   26.00(2)   -2.058(4)   26.21    -1.823  20000  0.004
1.0   6.0   37.06(3)   -1.361(6)   37.32    -1.100  20000  0.002
1.1   6.0   52.25(2)   -0.216(4)   52.57     0.072  20000  0.002
1.2   6.0   72.90(5)    1.502(9)   73.28     1.816  20000  0.002
1.25  6.0   85.71(5)    2.612(8)   86.12     2.939  20000  0.002

Загрузка в этот набор данных с использованием np.loadtxt не удается из-за неопределенности для значений P* и U*. Есть ли встроенный инструмент для обработки этого, чтобы избежать ручного редактирования файлов данных?

Я рассматриваю пакет неопределенностей как возможное решение, но мне интересно, есть ли у numpy что-то для этого.

2 ответа

Решение
In [1]: txt=b"""# p*  T*     P*         U*          P*_cs    U*_cs  Steps  dt*
   ...: 0.1   6.0    0.6499(6) -0.478(2)    0.6525  -0.452  30000  0.002
   ...: 0.2   6.0    1.442(1)  -0.942(2)    1.452   -0.890  30000  0.002
   ...: 0.3   6.0    2.465(3)  -1.376(1)    2.489   -1.298  30000  0.002"""
In [2]: txt=txt.splitlines()

txt файловая подстановка (строка байтов в PY3)

In [3]: data=np.genfromtxt(txt, dtype=None, names=True)
In [4]: data
Out[4]: 
array([(0.1, 6.0, b'0.6499(6)', b'-0.478(2)', 0.6525, -0.452, 30000, 0.002),
       (0.2, 6.0, b'1.442(1)', b'-0.942(2)', 1.452, -0.89, 30000, 0.002),
       (0.3, 6.0, b'2.465(3)', b'-1.376(1)', 2.489, -1.298, 30000, 0.002)], 
      dtype=[('p', '<f8'), ('T', '<f8'), ('P', 'S9'), ('U', 'S9'), ('P_cs', '<f8'), ('U_cs', '<f8'), ('Steps', '<i4'), ('dt', '<f8')])

'P' и 'U' загружаются как строки, потому что они не могут быть проанализированы как числа.

Теперь определите converter который снимает () часть (снова с байтами)

def rmvpar(astr):
   return float(astr.split(b'(')[0])

In [9]: data=np.genfromtxt(txt, dtype=None, names=True, 
      converters={2:rmvpar, 3:rmvpar})
In [10]: data
Out[10]: 
array([(0.1, 6.0, 0.6499, -0.478, 0.6525, -0.452, 30000, 0.002),
       (0.2, 6.0, 1.442, -0.942, 1.452, -0.89, 30000, 0.002),
       (0.3, 6.0, 2.465, -1.376, 2.489, -1.298, 30000, 0.002)], 
      dtype=[('p', '<f8'), ('T', '<f8'), ('P', '<f8'), ('U', '<f8'), ('P_cs', '<f8'), ('U_cs', '<f8'), ('Steps', '<i4'), ('dt', '<f8')])

Теперь эти два поля являются поплавками.

Но конвертеры не могут вернуть два числа, поэтому я не могу сохранить неопределенность таким образом.

Другой подход - пропустить строки через функцию фильтра.

def splt(astr):
    strs=astr.split()
    def foo(astr):
        if b'(' in astr:
            astr = astr.strip(b')').split(b'(')
            return b','.join(astr)
        return astr
    return b','.join([foo(a) for a in strs])

In [26]: [splt(line) for line in txt]
Out[26]: 
[b'#,p*,T*,P*,U*,P*_cs,U*_cs,Steps,dt*',
 b'0.1,6.0,0.6499,6,-0.478,2,0.6525,-0.452,30000,0.002',
 b'0.2,6.0,1.442,1,-0.942,2,1.452,-0.890,30000,0.002',
 b'0.3,6.0,2.465,3,-1.376,1,2.489,-1.298,30000,0.002']

Чтобы использовать это, я должен пропустить заголовок, потому что новые строки имеют два добавленных столбца

In [28]: data=np.genfromtxt([splt(line) for line in txt], delimiter=',',dtype=None, skip_header=1)
In [29]: data
Out[29]: 
array([(0.1, 6.0, 0.6499, 6, -0.478, 2, 0.6525, -0.452, 30000, 0.002),
       (0.2, 6.0, 1.442, 1, -0.942, 2, 1.452, -0.89, 30000, 0.002),
       (0.3, 6.0, 2.465, 3, -1.376, 1, 2.489, -1.298, 30000, 0.002)], 
      dtype=[('f0', '<f8'), ('f1', '<f8'), ('f2', '<f8'), ('f3', '<i4'), 
             ('f4', '<f8'), ('f5', '<i4'), ('f6', '<f8'), ('f7', '<f8'), 
             ('f8', '<i4'), ('f9', '<f8')])

Но я мог бы изменить оригинал dtype сделать 2 поля (под) массива:

In [30]: dt=np.dtype([('p', '<f8'), ('T', '<f8'), ('P', '<f8',(2,)), 
                ('U', '<f8',(2,)), ('P_cs', '<f8'), ('U_cs', '<f8'), 
                ('Steps', '<i4'), ('dt', '<f8')])

In [31]: data = np.genfromtxt((splt(line) for line in txt), delimiter=',',dtype=dt, skip_header=1)
In [32]: data
Out[32]: 
array([(0.1, 6.0, [0.6499, 6.0], [-0.478, 2.0], 0.6525, -0.452, 30000, 0.002),
       (0.2, 6.0, [1.442, 1.0], [-0.942, 2.0], 1.452, -0.89, 30000, 0.002),
       (0.3, 6.0, [2.465, 3.0], [-1.376, 1.0], 2.489, -1.298, 30000, 0.002)], 
      dtype=[('p', '<f8'), ('T', '<f8'), ('P', '<f8', (2,)), ('U', '<f8', (2,)), 
             ('P_cs', '<f8'), ('U_cs', '<f8'), ('Steps', '<i4'), ('dt', '<f8')])

Такое поле будет выглядеть так:

In [33]: data['P']
Out[33]: 
array([[ 0.6499,  6.    ],
       [ 1.442 ,  1.    ],
       [ 2.465 ,  3.    ]])

Я мог бы определить другие dtypesдо тех пор, пока количество полей совпадают.

С файлом вместо этих текстовых строк я бы использовал что-то вроде (не проверено):

with open(filename,'wb') as f:
    data = np.genfromtxt((splt(line) for line in f),...

Здесь и выше я использую выражение генератора (splt(line) for line in x)Хотя понимание списка было бы хорошо. Любой код, который открывает файл и возвращает / возвращает измененные строки, будет работать.

Нет, в NumPy ничего подобного нет. Вам либо понадобится внешний пакет (даже Pandas этого не сделает), либо вы можете загрузить столбцы в виде строк вместо чисел и обработать их самостоятельно. Для строкового подхода str методы в Pandas могут быть полезны, например, http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.str.split.html

Все это говорит, что даже не ясно, как бы вы хотели представить это после загрузки данных. Вы хотите просто игнорировать скобки? Вы хотите записать количество неопределенных цифр в дополнительном столбце? И то, и другое возможно, и, вероятно, проще в Пандах, чем в NumPy.

Другие вопросы по тегам