Python 仅取大熊猫中两个连续值的平均值
我有一个非均匀分布的数据帧,比如Python 仅取大熊猫中两个连续值的平均值,python,pandas,Python,Pandas,我有一个非均匀分布的数据帧,比如 2013-05-16 17:33:30 485.75 NaN NaN 2013-05-16 17:34:00 479.16 NaN NaN 2013-05-16 17:35:30 NaN 429.90 NaN 2013-05-16 17:36:00 NaN 433.39 NaN 2013-05-16 17:37:30 NaN NaN 415.94 2013-05-16 17
2013-05-16 17:33:30 485.75 NaN NaN
2013-05-16 17:34:00 479.16 NaN NaN
2013-05-16 17:35:30 NaN 429.90 NaN
2013-05-16 17:36:00 NaN 433.39 NaN
2013-05-16 17:37:30 NaN NaN 415.94
2013-05-16 17:38:00 NaN NaN 401.59
2013-05-16 17:49:30 432.23 NaN NaN
2013-05-16 17:51:00 NaN 424.08 NaN
2013-05-16 17:52:30 NaN NaN 411.67
2013-05-16 18:01:30 471.01 NaN NaN
2013-05-16 18:02:00 474.11 NaN NaN
2013-05-16 18:03:30 NaN 440.76 NaN
2013-05-16 18:04:00 NaN 438.82 NaN
2013-05-16 18:17:30 469.46 NaN NaN
2013-05-16 18:18:00 460.93 NaN NaN
我可以分别对待每一列。因此,对于每一列,我可以有一个、两个、三个甚至四个连续的值,这些值由nan
s包围。我想做的是一次只取两个连续的行,用它们的平均值替换它们的值,用它们的平均值替换它们的索引。因此,我将用值和索引的平均值替换任意两行连续的值,只替换一行。因此,上面的例子将成为
2013-05-16 17:33:45 482.45 NaN NaN
2013-05-16 17:35:45 NaN 431.69 NaN
2013-05-16 17:37:45 NaN NaN 408.76
2013-05-16 17:49:30 432.23 NaN NaN
2013-05-16 17:51:00 NaN 424.08 NaN
2013-05-16 17:52:30 NaN NaN 411.67
2013-05-16 18:01:45 472.56 NaN NaN
2013-05-16 18:03:45 NaN 439.78 NaN
2013-05-16 18:17:45 465.19 NaN NaN
因此,将对连续的值进行平均,只保留一个值的行。我尝试过类似于df.resample('30s')。resample('2min')
或(df+df.shift(1))/2
,但到目前为止没有成功。有什么想法吗
注意:对于每一行,只有一列有值,其他列总是NaN
您可以首先datetimeindex
到Unix time
,然后从index
创建新列,获取每列的mean
。通过以下方式将Unix时间最后转换为日期时间:
说明:
首先,您需要从值创建组,其中列包含数字。您需要使用值0
,因为有时函数返回后的第一个值NaN
。在此示例中,它仅为列a
。但在实际数据中,它也可以位于列b
和列c
中
df1 = pd.DataFrame( {'isnull': df.a.isnull()})
df1['diff'] = df1['isnull'].diff()
df1['cumsum'] = df1['diff'].cumsum().fillna(0)
print df1
isnull diff cumsum
0 False NaN 0.0
1 False False 0.0
2 True True 1.0
3 True False 1.0
4 True False 1.0
5 True False 1.0
6 False True 2.0
7 True True 3.0
8 True False 3.0
9 False True 4.0
10 False False 4.0
11 True True 5.0
12 True False 5.0
13 False True 6.0
14 False False 6.0
然后,您可以按此分组并聚合。因为您丢失了索引
,所以我创建了新的列索引
,它也是聚合的。然后,我从列索引
,只过滤一列a
、b
或c
,因为我通过这个新索引聚合了所有数据帧
print df.groupby(df.a.isnull().cumsum().fillna(0)).mean()
index a b c
a
0 1368725625 482.455 NaN NaN
1 1368725730 NaN 429.90 NaN
2 1368725760 NaN 433.39 NaN
3 1368725850 NaN NaN 415.94
4 1368726225 432.230 NaN 401.59
5 1368726660 NaN 424.08 NaN
6 1368727120 472.560 NaN 411.67
7 1368727410 NaN 440.76 NaN
8 1368727990 465.195 438.82 NaN
如果您需要更自动的aproach,请使用:
#convert to unix time (need integers from datetime for mean)
df.index = df.index.astype(np.int64) // 10**9
#create column index from df.index
df = df.reset_index()
#print df
dfs = []
#select all columns without first index column
for col in df.columns[1:]:
dfs.append(df.groupby(df[col].isnull().diff().cumsum().fillna(0)).mean().set_index('index')[[col]])
df = pd.concat(dfs, axis=1)
#drop rows with all NaN
df = df.dropna(how='all').rename_axis(None)
#convert unix time to datetime
df.index = pd.to_datetime(df.index, unit='s')
print df
a b c
2013-05-16 17:33:45 482.455 NaN NaN
2013-05-16 17:35:45 NaN 431.645 NaN
2013-05-16 17:37:45 NaN NaN 408.765
2013-05-16 17:49:30 432.230 NaN NaN
2013-05-16 17:51:00 NaN 424.080 NaN
2013-05-16 17:52:30 NaN NaN 411.670
2013-05-16 18:01:45 472.560 NaN NaN
2013-05-16 18:03:45 NaN 439.790 NaN
2013-05-16 18:17:45 465.195 NaN NaN
我想知道是否有一种方法可以避免手动设置每一列,并使其更加自动化。答案不错。答案已编辑,请检查。抱歉耽搁了。谢谢,您的编辑正是我40分钟前实现您的答案时所做的:)我指的是一种不必循环浏览专栏的方式(抱歉,我不是很清楚)。我认为在
数据帧列表中添加dfs
的方法很好地实现为concat
函数中的输入。
df1 = pd.DataFrame( {'isnull': df.a.isnull()})
df1['diff'] = df1['isnull'].diff()
df1['cumsum'] = df1['diff'].cumsum().fillna(0)
print df1
isnull diff cumsum
0 False NaN 0.0
1 False False 0.0
2 True True 1.0
3 True False 1.0
4 True False 1.0
5 True False 1.0
6 False True 2.0
7 True True 3.0
8 True False 3.0
9 False True 4.0
10 False False 4.0
11 True True 5.0
12 True False 5.0
13 False True 6.0
14 False False 6.0
print df.groupby(df.a.isnull().cumsum().fillna(0)).mean()
index a b c
a
0 1368725625 482.455 NaN NaN
1 1368725730 NaN 429.90 NaN
2 1368725760 NaN 433.39 NaN
3 1368725850 NaN NaN 415.94
4 1368726225 432.230 NaN 401.59
5 1368726660 NaN 424.08 NaN
6 1368727120 472.560 NaN 411.67
7 1368727410 NaN 440.76 NaN
8 1368727990 465.195 438.82 NaN
print df.groupby(df.a.isnull().cumsum().fillna(0)).mean().set_index('index')
a b c
index
1368725625 482.455 NaN NaN
1368725730 NaN 429.90 NaN
1368725760 NaN 433.39 NaN
1368725850 NaN NaN 415.94
1368726225 432.230 NaN 401.59
1368726660 NaN 424.08 NaN
1368727120 472.560 NaN 411.67
1368727410 NaN 440.76 NaN
1368727990 465.195 438.82 NaN
print df.groupby(df.a.isnull().cumsum().fillna(0)).mean().set_index('index')[['a']]
a
index
1368725625 482.455
1368725730 NaN
1368725760 NaN
1368725850 NaN
1368726225 432.230
1368726660 NaN
1368727120 472.560
1368727410 NaN
1368727990 465.195
#convert to unix time (need integers from datetime for mean)
df.index = df.index.astype(np.int64) // 10**9
#create column index from df.index
df = df.reset_index()
#print df
dfs = []
#select all columns without first index column
for col in df.columns[1:]:
dfs.append(df.groupby(df[col].isnull().diff().cumsum().fillna(0)).mean().set_index('index')[[col]])
df = pd.concat(dfs, axis=1)
#drop rows with all NaN
df = df.dropna(how='all').rename_axis(None)
#convert unix time to datetime
df.index = pd.to_datetime(df.index, unit='s')
print df
a b c
2013-05-16 17:33:45 482.455 NaN NaN
2013-05-16 17:35:45 NaN 431.645 NaN
2013-05-16 17:37:45 NaN NaN 408.765
2013-05-16 17:49:30 432.230 NaN NaN
2013-05-16 17:51:00 NaN 424.080 NaN
2013-05-16 17:52:30 NaN NaN 411.670
2013-05-16 18:01:45 472.560 NaN NaN
2013-05-16 18:03:45 NaN 439.790 NaN
2013-05-16 18:17:45 465.195 NaN NaN