使用多个 numpy 数组+标量编写 txt 文件的语法是什么以及如何再次读取它?
What is the syntax for writing txt file with multiple numpy arrays+scalars and how to read it in again?
我有 2 个相同长度的 numpy 数组,我们称它们为 A 和 B 以及 2 个标量值,名为 C 和 D。我想将这些值存储到一个 txt 文件中。我想到了如下结构:
不一定非要这种格式,我只是觉得它方便明了。我知道如何将 numpy 数组写入 txt 文件并再次读出它们,但我很难将 txt 文件写为数组和标量值的组合以及如何将它们从 txt 再次读出到 numpy。
A = np.array([1, 2, 3, 4, 5])
B = np.array([5, 4, 3, 2, 1])
C = [6]
D = [7]
np.savetxt('file.txt', (A, B))
A_B_load = np.loadtxt('file.txt')
A_load = A_B_load[0,:]
B_load= A_B_load[1,:]
这并没有给我建议的列结构,而是将数组存储在行中,但这并不重要。
我找到了一个有点不方便的解决方案,因为我必须用 0 填充标量值才能使它们与数组 A 和 B 具有相同的长度,因此必须有一个更智能的解决方案。
A = np.array([1, 2, 3, 4, 5])
B = np.array([5, 4, 3, 2, 1])
C = [6]
D = [7]
fill = np.zeros(len(A)-1)
C = np.concatenate((C,fill))
D = np.concatenate((D, fill))
np.savetxt('file.txt', (A,B,C,D))
A_B_load = np.loadtxt('file.txt')
A_load = A_B_load[0,:]
B_load = A_B_load[1,:]
C_load = A_B_load[2,0]
D_load = A_B_load[3,0]
更聪明的解决方案可能是使用 pandas 而不是 numpy(如果您可以选择):
df = pd.concat([pd.DataFrame(arr) for arr in [A,B,C,D]], axis=1)
df.to_csv("test.txt", na_rep="", sep=" ", header=False, index=False)
a = pd.read_csv("test.txt", sep=" ", header=None).values
第一行通过连接所有数组创建数据框。 Pandas' 默认行为是用 NaN 替换缺失值。第二行写入输出文件,用空字符串替换 NaNs(因为您似乎关心文件大小)。最后一行给你一个 numpy 数组:
In [45]: a
Out[45]:
array([[ 1., 5., 6., 7.],
[ 2., 4., nan, nan],
[ 3., 3., nan, nan],
[ 4., 2., nan, nan],
[ 5., 1., nan, nan]])
编辑:
由于您输入的是整数类型,
In [20]: A.dtype
Out[20]: dtype('int64')
更准确地说是 64-bit signed integer
,您可能想要找回相同的类型。
要做到这一点,只需执行以下操作:
a = pd.read_csv("test.txt", sep=" ", header=None).fillna(0).astype(np.int)
因此,您首先用零替换 NaN,因为无论如何您都不使用这些值,然后将所有内容直接转换为 np.int
(pandas' Int64
将支持 NA
值,但是你应该再次将你的数组转换为 numpy 的 int64
,所以这是不值得的)。
你会得到一个 pandas DataFrame
:
In [63]: a
Out[63]:
0 1 2 3
0 1 5 6 7
1 2 4 0 0
2 3 3 0 0
3 4 2 0 0
4 5 1 0 0
您可以从中轻松取回数组:
A = a[0].to_numpy(); B=a[1].to_numpy(); C=a.iloc[0,2]; D=a.iloc[0,3]
In [123]: A = np.array([1, 2, 3, 4, 5])
...: B = np.array([5, 4, 3, 2, 1])
...: C = [6]
...: D = [7]
savetxt
旨在以一致的 csv 格式编写二维数组 - 整洁的 table 每行中的列数相同。
In [124]: arr = np.stack((A,B), axis=1)
In [125]: arr
Out[125]:
array([[1, 5],
[2, 4],
[3, 3],
[4, 2],
[5, 1]])
这是一种可能的写入格式:
In [126]: np.savetxt('foo.txt', arr, fmt='%d', header=f'{C} {D}', delimiter=',')
...:
In [127]: cat foo.txt
# [6] [7]
1,5
2,4
3,3
4,2
5,1
我将标量放在 header 行中,因为它们与数组不匹配。
loadtxt
可以重新创建 arr
数组:
In [129]: data = np.loadtxt('foo.txt', dtype=int, skiprows=1, delimiter=',')
In [130]: data
Out[130]:
array([[1, 5],
[2, 4],
[3, 3],
[4, 2],
[5, 1]])
header 行可以这样读:
In [138]: with open('foo.txt') as f:
...: header = f.readline().strip()
...: line = header[1:]
...:
In [139]: line
Out[139]: ' [6] [7]'
我应该将其保存为更易于解析的内容,例如“# 6,7”
您接受的答案在 csv
中创建了一个包含 nan
个值和空白的数据框
In [143]: import pandas as pd
In [144]: df = pd.concat([pd.DataFrame(arr) for arr in [A,B,C,D]], axis=1)
...: df.to_csv("test.txt", na_rep="", sep=" ", header=False, index=False)
In [145]: df
Out[145]:
0 0 0 0
0 1 5 6.0 7.0
1 2 4 NaN NaN
2 3 3 NaN NaN
3 4 2 NaN NaN
4 5 1 NaN NaN
In [146]: cat test.txt
1 5 6.0 7.0
2 4
3 3
4 2
5 1
请注意 np.nan
是一个浮点数,因此一些列是浮点数。 loadtxt
无法处理那些“空白”列; np.genfromtxt
在这方面更好,但它需要像 ,
这样的分隔符来标记它们。
写入和读取全长数组很容易。但是混合类型变得混乱。
这是一种更易于编写和阅读的格式:
In [149]: arr = np.zeros((5,4),int)
...: for i,var in enumerate([A,B,C,D]):
...: arr[:,i] = var
...:
In [150]: arr
Out[150]:
array([[1, 5, 6, 7],
[2, 4, 6, 7],
[3, 3, 6, 7],
[4, 2, 6, 7],
[5, 1, 6, 7]])
In [151]: np.savetxt('foo.txt', arr, fmt='%d', delimiter=',')
In [152]: cat foo.txt
1,5,6,7
2,4,6,7
3,3,6,7
4,2,6,7
5,1,6,7
In [153]: np.loadtxt('foo.txt', delimiter=',', dtype=int)
Out[153]:
array([[1, 5, 6, 7],
[2, 4, 6, 7],
[3, 3, 6, 7],
[4, 2, 6, 7],
[5, 1, 6, 7]])
我有 2 个相同长度的 numpy 数组,我们称它们为 A 和 B 以及 2 个标量值,名为 C 和 D。我想将这些值存储到一个 txt 文件中。我想到了如下结构:
不一定非要这种格式,我只是觉得它方便明了。我知道如何将 numpy 数组写入 txt 文件并再次读出它们,但我很难将 txt 文件写为数组和标量值的组合以及如何将它们从 txt 再次读出到 numpy。
A = np.array([1, 2, 3, 4, 5])
B = np.array([5, 4, 3, 2, 1])
C = [6]
D = [7]
np.savetxt('file.txt', (A, B))
A_B_load = np.loadtxt('file.txt')
A_load = A_B_load[0,:]
B_load= A_B_load[1,:]
这并没有给我建议的列结构,而是将数组存储在行中,但这并不重要。
我找到了一个有点不方便的解决方案,因为我必须用 0 填充标量值才能使它们与数组 A 和 B 具有相同的长度,因此必须有一个更智能的解决方案。
A = np.array([1, 2, 3, 4, 5])
B = np.array([5, 4, 3, 2, 1])
C = [6]
D = [7]
fill = np.zeros(len(A)-1)
C = np.concatenate((C,fill))
D = np.concatenate((D, fill))
np.savetxt('file.txt', (A,B,C,D))
A_B_load = np.loadtxt('file.txt')
A_load = A_B_load[0,:]
B_load = A_B_load[1,:]
C_load = A_B_load[2,0]
D_load = A_B_load[3,0]
更聪明的解决方案可能是使用 pandas 而不是 numpy(如果您可以选择):
df = pd.concat([pd.DataFrame(arr) for arr in [A,B,C,D]], axis=1)
df.to_csv("test.txt", na_rep="", sep=" ", header=False, index=False)
a = pd.read_csv("test.txt", sep=" ", header=None).values
第一行通过连接所有数组创建数据框。 Pandas' 默认行为是用 NaN 替换缺失值。第二行写入输出文件,用空字符串替换 NaNs(因为您似乎关心文件大小)。最后一行给你一个 numpy 数组:
In [45]: a
Out[45]:
array([[ 1., 5., 6., 7.],
[ 2., 4., nan, nan],
[ 3., 3., nan, nan],
[ 4., 2., nan, nan],
[ 5., 1., nan, nan]])
编辑:
由于您输入的是整数类型,
In [20]: A.dtype
Out[20]: dtype('int64')
更准确地说是 64-bit signed integer
,您可能想要找回相同的类型。
要做到这一点,只需执行以下操作:
a = pd.read_csv("test.txt", sep=" ", header=None).fillna(0).astype(np.int)
因此,您首先用零替换 NaN,因为无论如何您都不使用这些值,然后将所有内容直接转换为 np.int
(pandas' Int64
将支持 NA
值,但是你应该再次将你的数组转换为 numpy 的 int64
,所以这是不值得的)。
你会得到一个 pandas DataFrame
:
In [63]: a
Out[63]:
0 1 2 3
0 1 5 6 7
1 2 4 0 0
2 3 3 0 0
3 4 2 0 0
4 5 1 0 0
您可以从中轻松取回数组:
A = a[0].to_numpy(); B=a[1].to_numpy(); C=a.iloc[0,2]; D=a.iloc[0,3]
In [123]: A = np.array([1, 2, 3, 4, 5])
...: B = np.array([5, 4, 3, 2, 1])
...: C = [6]
...: D = [7]
savetxt
旨在以一致的 csv 格式编写二维数组 - 整洁的 table 每行中的列数相同。
In [124]: arr = np.stack((A,B), axis=1)
In [125]: arr
Out[125]:
array([[1, 5],
[2, 4],
[3, 3],
[4, 2],
[5, 1]])
这是一种可能的写入格式:
In [126]: np.savetxt('foo.txt', arr, fmt='%d', header=f'{C} {D}', delimiter=',')
...:
In [127]: cat foo.txt
# [6] [7]
1,5
2,4
3,3
4,2
5,1
我将标量放在 header 行中,因为它们与数组不匹配。
loadtxt
可以重新创建 arr
数组:
In [129]: data = np.loadtxt('foo.txt', dtype=int, skiprows=1, delimiter=',')
In [130]: data
Out[130]:
array([[1, 5],
[2, 4],
[3, 3],
[4, 2],
[5, 1]])
header 行可以这样读:
In [138]: with open('foo.txt') as f:
...: header = f.readline().strip()
...: line = header[1:]
...:
In [139]: line
Out[139]: ' [6] [7]'
我应该将其保存为更易于解析的内容,例如“# 6,7”
您接受的答案在 csv
中创建了一个包含nan
个值和空白的数据框
In [143]: import pandas as pd
In [144]: df = pd.concat([pd.DataFrame(arr) for arr in [A,B,C,D]], axis=1)
...: df.to_csv("test.txt", na_rep="", sep=" ", header=False, index=False)
In [145]: df
Out[145]:
0 0 0 0
0 1 5 6.0 7.0
1 2 4 NaN NaN
2 3 3 NaN NaN
3 4 2 NaN NaN
4 5 1 NaN NaN
In [146]: cat test.txt
1 5 6.0 7.0
2 4
3 3
4 2
5 1
请注意 np.nan
是一个浮点数,因此一些列是浮点数。 loadtxt
无法处理那些“空白”列; np.genfromtxt
在这方面更好,但它需要像 ,
这样的分隔符来标记它们。
写入和读取全长数组很容易。但是混合类型变得混乱。
这是一种更易于编写和阅读的格式:
In [149]: arr = np.zeros((5,4),int)
...: for i,var in enumerate([A,B,C,D]):
...: arr[:,i] = var
...:
In [150]: arr
Out[150]:
array([[1, 5, 6, 7],
[2, 4, 6, 7],
[3, 3, 6, 7],
[4, 2, 6, 7],
[5, 1, 6, 7]])
In [151]: np.savetxt('foo.txt', arr, fmt='%d', delimiter=',')
In [152]: cat foo.txt
1,5,6,7
2,4,6,7
3,3,6,7
4,2,6,7
5,1,6,7
In [153]: np.loadtxt('foo.txt', delimiter=',', dtype=int)
Out[153]:
array([[1, 5, 6, 7],
[2, 4, 6, 7],
[3, 3, 6, 7],
[4, 2, 6, 7],
[5, 1, 6, 7]])