这个问题与我之前提出的一个问题 (Remapping `numpy.array` with missing values) 有点相关,当时我正在努力处理缺少数据的时间序列,有人建议“使用 Pandas!”。所以我来了...
我正在处理大型数据集,基本上由来自不同观察站点的时间序列组成,我想对这些站点进行统计比较。这些数据集相当困惑;许多丢失的数据(用例如 -99
表示),丢失的时间记录(一个站可能有时间记录,另一个没有),我只想包含/比较数据(1)所有站点具有某个变量的数据,或者 (2) 我想比较的两个站点具有该变量的数据,而忽略其他站点是否(没有)具有数据。
以这个最小的例子为例:
import pandas as pd
from io import StringIO
data = StringIO("""\
1, 2001-01-01, 00:00, 1.0, 0.5, 1.0
1, 2001-01-01, 01:00, 1.1, 0.6, 2.0
1, 2001-01-01, 02:00, 1.2, 0.7, 3.0
1, 2001-01-01, 03:00, 1.3, 0.8, 4.0
2, 2001-01-01, 00:00, 2.0, -99, -99
2, 2001-01-01, 01:00, -99, 1.6, 2.0
2, 2001-01-01, 02:00, 2.2, 1.7, 3.0
2, 2001-01-01, 03:00, 2.3, 1.8, 4.0
3, 2001-01-01, 00:00, 3.0, 2.5, 1.0
3, 2001-01-01, 01:00, 3.1, 2.6, -99
3, 2001-01-01, 02:00, -99, -99, 3.0
3, 2001-01-01, 03:00, 3.3, 2.8, 4.0
3, 2001-01-01, 04:00, 3.4, 2.9, 5.0
""")
columns = ['id','date','time','T','Td','cc']
df = pd.read_table(data, header=None, names=columns, delimiter=',', na_values=-99, parse_dates=[['date','time']])
其中-99
表示缺失值。我想比较来自不同站点(列 id
)的数据(列 T
、Td
、cc
) ,但如前所述,仅当两个或所有 id
具有我感兴趣的变量的数据时(完全忽略其他列中的数据是否丢失)。
因此对于此示例,如果所有站点都需要数据,则比较 T
只会导致比较来自 2001-01-01, 00:00
和 03:00
,因为对于其他时间,id=2
或 id=3
缺少 T
,并且id=3
的最后一次记录在其他 id
中完全不存在。
我已经玩了几个小时了,但老实说我真的不知道从哪里开始。是否可以使用上述标准提取大小为 n_sites x n_valid_values
(3x2
,对于本例)的 numpy.array
,我可以将其用于进一步分析?
EDIT 作为一个部分的,但真的(真的)丑陋的解决方案,这样的事情似乎可行:
# Loop over all indexes where T is nan:
for i in np.where(df['T'].isnull())[0]:
# For each of them, set records with the same date_time to nan
j = np.where(df['date_time'] == df['date_time'][i])[0]
df['T'][j] = np.nan
# Drop all records where T is nan
df2 = df.dropna(subset=['T'])
# Group by the different stations:
g = df2.groupby('id')
# Get the arrays (could automate this based on the unique id's):
v1 = g.get_group(1)['T']
v2 = g.get_group(2)['T']
v3 = g.get_group(3)['T']
但这仍然没有删除 id=3
, date_time=2001-01-01, 04:00
的记录,我猜/希望那里是使用 Pandas
的更优雅的方法。
最佳答案
一种似乎有效的方法(基于此:https://stackoverflow.com/a/34985243/3581217 答案)是创建一个 Dataframe
,其中来自不同站点的观察结果具有不同的列,然后是一个 dropna()
将 subset
设置为所有列或我要比较的两个站点,这会删除所有缺少数据的行。
import pandas as pd
import numpy as np
from io import StringIO
data1 = StringIO("""\
1, 2001-01-01, 00:00, 1.0
1, 2001-01-01, 01:00, 1.1
1, 2001-01-01, 02:00, 1.2
1, 2001-01-01, 03:00, 1.3
""")
data2 = StringIO("""\
2, 2001-01-01, 00:00, 2.0
2, 2001-01-01, 01:00, -99
2, 2001-01-01, 02:00, 2.2
2, 2001-01-01, 03:00, 2.3
""")
data3 = StringIO("""\
3, 2001-01-01, 00:00, 3.0
3, 2001-01-01, 01:00, 3.1
3, 2001-01-01, 02:00, -99
3, 2001-01-01, 03:00, 3.3
3, 2001-01-01, 04:00, 3.4
""")
columns = ['id','date','time','T1']
df1 = pd.read_table(data1, header=None, names=columns, delimiter=',', na_values=-99, parse_dates=[['date','time']])
columns = ['id','date','time','T2']
df2 = pd.read_table(data2, header=None, names=columns, delimiter=',', na_values=-99, parse_dates=[['date','time']])
columns = ['id','date','time','T3']
df3 = pd.read_table(data3, header=None, names=columns, delimiter=',', na_values=-99, parse_dates=[['date','time']])
df = pd.concat([df1,df2,df3]).groupby('date_time').max()
df = df.dropna(subset=['T1','T2','T3'])
生成的 Dataframe
如下所示:
In [232]: df
Out[232]:
T1 T2 T3 id
date_time
2001-01-01 00:00:00 1.0 2.0 3.0 3
2001-01-01 03:00:00 1.3 2.3 3.3 3
如果我只想比较两个站点,在这种情况下忽略 T3
,df.dropna(subset=['T1','T2'])
结果:
In [234]: df
Out[234]:
T1 T2 T3 id
date_time
2001-01-01 00:00:00 1.0 2.0 3.0 3
2001-01-01 02:00:00 1.2 2.2 NaN 3
2001-01-01 03:00:00 1.3 2.3 3.3 3
这是要走的路吗?仍然感觉有点不像 Pandas ......?
关于python - Pandas 时间序列与缺失数据/记录的比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39854373/