Python 使用ython读取文本文件中不带空格的数字
我是Python的新手,很难阅读这样的文本文件:Python 使用ython读取文本文件中不带空格的数字,python,Python,我是Python的新手,很难阅读这样的文本文件: 0.42617E-03-0.19725E+09-0.21139E+09 0.37077E+08 0.85234E-03-0.18031E+09-0.18340E+09 0.28237E+08 0.12785E-02-0.16583E+09-0.15887E+09 0.20637E+08 因此,文件中的数字之间没有逗号或空格分隔符。 使用Matlab我知道如何指定格式,但如何在Python中实现 我一直在尝试np.loadtxt,但不
0.42617E-03-0.19725E+09-0.21139E+09 0.37077E+08
0.85234E-03-0.18031E+09-0.18340E+09 0.28237E+08
0.12785E-02-0.16583E+09-0.15887E+09 0.20637E+08
因此,文件中的数字之间没有逗号或空格分隔符。
使用Matlab我知道如何指定格式,但如何在Python中实现
我一直在尝试np.loadtxt,但不知道如何设置要读取的位数,所以如果有人能给我一个提示,我将不胜感激
提前感谢,,
Erik为了扩展我的评论,基于您可以用MATLAB成功解析这个事实,我假设这些字段是固定宽度的。在这种情况下,您可以根据字段宽度对每一行进行切片,然后根据需要将其转换为numpy数组。例如:
import numpy
input_data = """ 0.42617E-03-0.19725E+09-0.21139E+09 0.37077E+08
0.85234E-03-0.18031E+09-0.18340E+09 0.28237E+08
0.12785E-02-0.16583E+09-0.15887E+09 0.20637E+08
"""
input_rows = input_data.split('\n')
width = 12
num_fields = 4
data = []
for input_row in input_rows:
if not input_row:
continue
data.append([float(input_row[width * i:width * (i + 1)].strip()) for i in range(num_fields)])
data = numpy.array(data)
print(data)
这将产生:
[[ 4.26170000e-04 -1.97250000e+08 -2.11390000e+08 3.70770000e+07]
[ 8.52340000e-04 -1.80310000e+08 -1.83400000e+08 2.82370000e+07]
[ 1.27850000e-03 -1.65830000e+08 -1.58870000e+08 2.06370000e+07]]
当然,本例使用固定字符串表示输入数据,但您可以想象对输入流执行类似的操作。您可能会滥用这样一个事实,即您的数字似乎都是用科学记数法表示的,并使用正则表达式来提取每个数字
import re
e_numbers = re.compile(r"[\d.]*?E[+-]\d{2}")
with open('yourfile.txt') as f:
numbers = [float(num) for lst in [e_numbers.findall(line) for line in f] for num in lst]
要拉出该正则表达式,请执行以下操作:
e_numbers = re.compile(r'''
[\d.]*? # zero or more of the following:
# 0123456789.
# matching the fewest possible
E # the literal letter 'E'
[+-] # either a literal '+' or a literal '-'
\d{2} # followed by two digits 0-9''', re.X)
其他答案使用的方法依赖于数字宽度相同的事实,或者使用科学方法。在这里,我提出了一个方法,它接受浮点数的任何表示,无论是否为固定宽度 如果用C语言处理给定的输入,可能会使用
scanf
或sscanf
。Python具有与printf
类似的功能(例如字符串的格式
方法),但它没有类似于scanf
或sscanf
的功能
幸运的是,您可以在Python标准库中直接使用sscanf
函数。以下示例适用于Linux系统上的Python:
导入ctypes
libc=ctypes.CDLL(“libc.so.6”)
sscanf=libc.sscanf
以开放(“测试”)作为fp:
对于fp中的l:
float_1=ctypes.c_float()
float_2=ctypes.c_float()
float_3=ctypes.c_float()
float_4=ctypes.c_float()
sscanf(ctypes.create_string_buffer(字节(l,“utf8”))、b“%f%f%f”、ctypes.byref(float_1)、ctypes.byref(float_2)、ctypes.byref(float_3)、ctypes.byref(float_4))
#您可以检查sscanf的返回值是否存在错误。当每个
打印(浮点值1.value、浮点值2.value、浮点值3.value、浮点值4.value)
输出是
0.00042617000872269273 -197250000.0 -211390000.0 37077000.0
0.0008523400174453855 -180310000.0 -183400000.0 28237000.0
0.0012784999562427402 -165830000.0 -158870000.0 20637000.0
如果您的系统不使用glibc或使用旧版本(不太可能),请相应地更改库的路径。(您的系统不太可能没有C库或该库不实现scanf)如果您使用的是Windows,请将libc=ctypes.CDLL(“libc.so.6”)
更改为
libc = ctypes.cdll.msvcrt # Loads MS standard C Library
ctypes
仅使用标准调用约定调用动态库中的函数。您可以使用它将Python代码与几乎任何C库进行接口
如果您不想使用
ctypes
,那么您可以使用一些社区库,例如或,它们都实现了scanf
的功能。我想您正在寻找split()
或regex
,如果需要的话?请说明您希望如何解析此内容。如果字段宽度是固定的,您可以使用切片。@JCVanHamme:它们看起来确实是固定宽度的---示例中的最后一列前面有一个空格,其中+
或-
与第一列一样(给定或获取标记格式错误)。这不是保证,但可能已经足够好了。我建议你查阅这些数据的来源,无论是个人还是程序。寻找某种标准,然后是产生它的代码,然后是任何“负责人”,他们可以告诉你输出应该遵守什么规则。如果你找不到这些数据的任何规则,你就会陷入猜测,不得不接受一个脆弱的“尚未打破”的解决方案。一行:np.array([[float(ln[(12*i:(12*(i+1))])for i in range(len(ln)/12)]for ln in open(“data.txt”))
这是一种有趣的切片方法。我更喜欢使用range的步骤
,因为它可以让您不必知道有多少个字段(或者确实需要做很多数学运算)<代码>[行[i:i+宽度]表示i在范围内(0,长度(行),宽度)]感谢您的所有回答。我没有让它工作,而是手动编辑文本文件以与“loadtxt”兼容。我真的是Python的新手(感觉阅读一个文件需要很多代码),在理解你的答案之前,我需要学习更多。