numpy 如何处理具有不确定值的数据文件,例如 0.6499(6)?
How does numpy handle data files with uncertainty values, e.g., 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
由于 P* 和 U* 值的不确定性,使用 np.loadtxt
加载此数据集失败。是否有内置工具来处理此问题以避免手动编辑数据文件?
我正在寻找 uncertainties 包作为一个可能的解决方案,但我想知道 numpy 是否已经有一些东西可以解决这个问题。
不,NumPy 中没有这样的东西。您将需要一个外部包(即使 Pandas 也不会这样做),或者您可以将列作为字符串而不是数字加载并自行处理。对于字符串方法,Pandas 中的 str
方法会有一些用处,例如http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.str.split.html
综上所述,甚至不清楚加载数据后您希望如何表示它。你想简单地忽略括号吗?您是否要在附加列中记录不确定数字的数量?两者都是可能的,而且在 Pandas 中可能比 NumPy 更容易。
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')])
现在这两个字段是浮点数。
但是转换器不能 return 两个数字,所以我不能这样保持不确定性。
另一种方法是通过过滤函数传递线条
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']
要使用它我必须跳过 header 因为新行有两个添加的列
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)
,尽管列表理解会很好。打开文件的任何代码和 yields/returns 修改后的行都将起作用。
这是我正在处理的一个大型数据集的片段:
# 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
由于 P* 和 U* 值的不确定性,使用 np.loadtxt
加载此数据集失败。是否有内置工具来处理此问题以避免手动编辑数据文件?
我正在寻找 uncertainties 包作为一个可能的解决方案,但我想知道 numpy 是否已经有一些东西可以解决这个问题。
不,NumPy 中没有这样的东西。您将需要一个外部包(即使 Pandas 也不会这样做),或者您可以将列作为字符串而不是数字加载并自行处理。对于字符串方法,Pandas 中的 str
方法会有一些用处,例如http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.str.split.html
综上所述,甚至不清楚加载数据后您希望如何表示它。你想简单地忽略括号吗?您是否要在附加列中记录不确定数字的数量?两者都是可能的,而且在 Pandas 中可能比 NumPy 更容易。
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')])
现在这两个字段是浮点数。
但是转换器不能 return 两个数字,所以我不能这样保持不确定性。
另一种方法是通过过滤函数传递线条
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']
要使用它我必须跳过 header 因为新行有两个添加的列
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)
,尽管列表理解会很好。打开文件的任何代码和 yields/returns 修改后的行都将起作用。