如何使用genfromtxt()在NumPy中读取长度不一的文本文件列?
我有几百个这样的文本文件,每一列之间用三个空格分开。这些数据是关于一年的:每个月12个月,每个月31天。
下面我只展示与问题相关的内容:
001 DIST - ADILABAD ANDHRA MEAN TEMP
DATE JAN FEB MAR . . . . NOV DEC
01 21.5 24.3 27.1 25.8 22.4
02 21.4 24.2 27.1 25.8 22.4
. . . . . .
. . . . . .
. . . . . .
27 23.6 26.8 30.3 23.1 21.3
28 23.8 27.0 30.6 22.9 21.3
29 23.4 31.0 22.9 21.2
30 23.5 31.1 22.6 21.4
31 23.8 31.2 . . . . 21.6
我想把每一列的数据读到一个数组里,然后计算平均值。
为此,我使用了 genfromtext()
函数,像这样:
import numpy as np
JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC = np.genfromtxt("tempmean_andhra_adilabad.txt", skiprows=3,
unpack=True, invalid_raise=False,
usecols=(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12),
autostrip=True)
正如你所看到的,我跳过了前三行和第一列,并把每一列的数据放入了一个数组中。如果不加 invalid_raise=False
,我会遇到以下错误:
Traceback (most recent call last):
File "pyshell#32", line 1, in 'module'
JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC = np.genfromtxt("temp mean_andhra_adilabad.txt",skiprows=3,unpack=True,usecols=(1,2,3,4,5,6,7,8,9,10,11,12),autostrip=True)
File "C:\Python27\lib\site-packages\numpy\lib\npyio.py", line 1667, in genfromtxt
raise ValueError(errmsg)
ValueError: Some errors were detected !
Line #32 (got 12 columns instead of 12)
Line #33 (got 12 columns instead of 12)
Line #34 (got 8 columns instead of 12)
我觉得这个问题可能是因为列的长度不同?或者是其他原因?
我想查看输出,所以我用了 invalid_raise=False
。现在我的问题是,当我打印任何一个数组,比如 JAN
,我只得到了28个元素。也就是说,每个数组只有28个元素。看起来每一列只读取了28行,因为 FEB
列只有28天。但我需要每个月的数据,比如 JAN
需要31个元素,JUNE
需要30个元素等等。
我该如何获取每个月的所有元素?
我觉得这是个非常基础的问题,但我对Python和 NumPy
非常陌生,才刚开始学习两个星期。我在StackOverflow和Google上搜索了很多问题,了解了如何跳过行、列等等。但我找不到与这个特定问题相关的答案。
请推荐一些模块、函数、代码等。
提前谢谢你。
2 个回答
更新
感谢Warren Weckesser指出,你可以传入宽度值,这样就能正确处理这个文件了。
没问题,pandas可以很好地读取固定宽度的文件:
In [192]:
df = pd.read_fwf(r'c:\data\temp mean_andhra_adilabad.txt',skiprows=2, widths=(5,)+(7,)*12, skip_footer=1)
df
Out[192]:
DATE JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV \
0 1 21.5 24.3 27.1 31.3 34.1 34.5 29.0 27.5 27.1 28.0 25.8
1 2 21.4 24.2 27.1 31.4 33.8 34.1 28.8 27.5 27.1 28.0 25.8
2 3 21.2 24.3 27.1 31.5 34.4 34.1 28.6 27.5 27.0 28.0 25.6
3 4 21.2 24.4 27.1 31.7 34.4 33.8 28.5 27.1 27.0 27.9 25.5
4 5 21.4 24.6 27.6 31.7 34.4 33.5 28.2 27.0 27.1 27.8 25.4
5 6 21.7 24.4 28.0 31.6 34.5 33.3 28.2 27.1 27.0 28.0 25.1
6 7 21.8 24.1 28.1 31.5 34.5 32.9 28.2 27.1 27.0 27.8 25.3
7 8 22.0 24.4 28.3 31.8 34.6 33.3 27.9 26.7 27.1 27.9 25.1
8 9 22.0 24.5 28.3 32.2 34.6 33.1 27.8 26.6 27.2 28.1 24.8
9 10 22.3 24.6 28.4 32.1 34.5 32.5 28.0 26.7 27.2 27.9 25.0
10 11 22.3 24.9 28.6 32.3 34.4 32.2 27.8 26.9 27.2 28.0 25.2
11 12 22.3 25.0 28.3 32.6 34.4 32.0 27.6 27.1 27.3 27.9 24.9
12 13 22.5 25.1 28.6 32.7 34.5 31.4 27.8 27.1 27.5 27.8 24.8
13 14 22.5 25.6 28.7 33.1 34.7 31.2 27.7 26.8 27.6 27.7 24.6
14 15 22.5 25.7 29.1 33.2 34.6 31.0 27.8 27.0 27.9 27.6 24.6
15 16 22.5 25.7 29.4 33.1 34.4 30.6 27.7 26.9 28.0 27.6 24.5
16 17 22.5 25.8 29.5 32.8 34.6 30.1 27.8 26.8 28.1 27.2 24.3
17 18 22.6 26.0 29.9 33.0 34.8 30.1 27.6 27.0 28.2 27.3 24.0
18 19 22.8 25.9 30.2 33.3 34.7 30.0 27.9 27.0 28.1 27.2 24.0
19 20 23.1 25.9 30.2 33.3 35.1 30.2 27.9 27.0 27.9 27.2 24.0
20 21 23.1 25.8 30.2 33.5 34.9 30.1 27.8 26.9 28.0 26.9 23.8
21 22 22.8 25.8 30.6 33.4 35.1 29.8 27.8 26.8 28.2 26.7 23.5
22 23 22.9 25.8 30.6 33.4 35.1 29.6 27.8 26.8 28.2 26.7 23.5
23 24 23.1 26.2 30.4 33.5 35.1 29.3 27.8 27.0 28.1 26.5 23.5
24 25 23.4 26.5 30.2 33.5 35.1 29.2 27.6 27.3 28.1 26.5 23.3
25 26 23.5 26.7 30.3 33.6 35.0 29.1 27.6 27.4 28.2 26.4 23.0
26 27 23.6 26.8 30.3 33.8 35.1 28.8 27.6 27.1 28.2 26.2 23.1
27 28 23.8 27.0 30.6 34.1 34.9 28.5 27.6 26.8 28.2 26.0 22.9
28 29 23.4 NaN 31.0 34.3 34.8 28.5 27.4 27.0 28.1 25.8 22.9
29 30 23.5 NaN 31.1 34.5 34.6 29.1 27.4 27.0 28.1 25.7 22.6
30 31 23.8 NaN 31.2 NaN 34.7 NaN 27.4 27.0 NaN 25.7 NaN
DEC
0 22.4
1 22.4
2 22.5
3 22.5
4 22.6
5 22.3
6 22.0
7 22.0
8 21.8
9 21.7
10 21.9
11 21.9
12 21.8
13 21.5
14 21.5
15 21.5
16 21.7
17 21.6
18 21.7
19 21.7
20 21.8
21 21.7
22 21.8
23 21.8
24 21.7
25 21.6
26 21.3
27 21.3
28 21.2
29 21.4
30 21.6
In [193]:
df.mean(axis=0)
Out[193]:
DATE 16.000000
JAN 22.548387
FEB 25.357143
MAR 29.229032
APR 32.793333
MAY 34.658065
JUN 31.196667
JUL 27.890323
AUG 27.016129
SEP 27.666667
OCT 27.225806
NOV 24.346667
DEC 21.812903
dtype: float64
你的数据不是用文本来分隔的,而是有固定宽度的列。正如@EdChum在他的回答中提到的,pandas有一个函数可以读取这种固定宽度的列数据。你也可以使用genfromtxt
,只需要在delimiter
参数中指定列的宽度。看起来这些字段的宽度是(4, 7, 7, 7, ...)。在下面的代码中,我会把它写成(4,) + (7,)*12
:
In [27]: (4,) + (7,)*12
Out[27]: (4, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7)
genfromtxt
默认使用的数据类型是np.float64
。如果某个字段无法转换为浮点数,它会被替换成nan
。所以在那些天数少于31天的月份末尾,数据会是nan
。
接下来,我把你的文件重命名为“temp_mean.txt”。注意你的文件最后有一个额外的空行,所以我也使用了skip_footer=1
这个参数。如果不使用这个参数,data
中会多出一行nan
值。
In [16]: data = genfromtxt("temp_mean.txt", skiprows=3, delimiter=(4,)+(7,)*12, usecols=range(1,13), skip_footer=1)
In [17]: data.shape
Out[17]: (31, 12)
In [18]: data[:,0] # JAN
Out[18]:
array([ 21.5, 21.4, 21.2, 21.2, 21.4, 21.7, 21.8, 22. , 22. ,
22.3, 22.3, 22.3, 22.5, 22.5, 22.5, 22.5, 22.5, 22.6,
22.8, 23.1, 23.1, 22.8, 22.9, 23.1, 23.4, 23.5, 23.6,
23.8, 23.4, 23.5, 23.8])
In [19]: data[:,1] # FEB
Out[19]:
array([ 24.3, 24.2, 24.3, 24.4, 24.6, 24.4, 24.1, 24.4, 24.5,
24.6, 24.9, 25. , 25.1, 25.6, 25.7, 25.7, 25.8, 26. ,
25.9, 25.9, 25.8, 25.8, 25.8, 26.2, 26.5, 26.7, 26.8,
27. , nan, nan, nan])
In [20]: data[-1,:] # Last row.
Out[20]:
array([ 23.8, nan, 31.2, nan, 34.7, nan, 27.4, 27. , nan,
25.7, nan, 21.6])
要计算每个月的平均值,你可以使用np.nanmean
:
In [21]: np.nanmean(data, axis=0)
Out[21]:
array([ 22.5483871 , 25.35714286, 29.22903226, 32.79333333,
34.65806452, 31.19666667, 27.89032258, 27.01612903,
27.66666667, 27.22580645, 24.34666667, 21.81290323])