Pandas 将方波边缘时间戳数据转换为适合打印的数据
这是我正在处理的数据的一个示例: 这是对布尔方波的描述,具有以下特征:Pandas 将方波边缘时间戳数据转换为适合打印的数据,pandas,bokeh,Pandas,Bokeh,这是我正在处理的数据的一个示例: 这是对布尔方波的描述,具有以下特征: “向下”列中的数字是随机整数,但总是被画成零 “向上”列中的数字也是随机整数,但始终绘制为1 大多数时候,“上”和“下”定期交替出现,但偶尔会出现额外的“下”或“上” 转换之间的延迟是不规则的,“时间”列中的值应被视为随机的,但是连续的(排序的) 这是我要找的bokeh代表: 需要同时查看原始点(包括重复点,如t=1.2的点)和线重叠 我的理解是,最简单的方法是在每一对之间插入一个点,y值是上一点的上/下值,x值是下一
- “向下”列中的数字是随机整数,但总是被画成零
- “向上”列中的数字也是随机整数,但始终绘制为1
- 大多数时候,“上”和“下”定期交替出现,但偶尔会出现额外的“下”或“上”
- 转换之间的延迟是不规则的,“时间”列中的值应被视为随机的,但是连续的(排序的)
一个好的解决方案将我的纯python代码替换为pandas代码。这应该让您开始学习。请注意,matplotlib是直接使用的,而不是pandas(实际上使用matplotlib)进行绘图
import pandas as pd
import matplotlib.pyplot as plt
将数据映射到熊猫:
data = pd.read_csv('wave_data.csv', sep=';')
def boolean_map(row):
if pd.notnull(row.Down):
return 0
else:
return 1
data['BooleanMapped'] = data.apply(boolean_map, axis=1)
绘制数据:
x = list(data['Time'])
y = list(data['BooleanMapped'])
plt.ylim(-0.1, 1.5)
plt.xlim(0.9, 2)
plt.step(x, y, where='post')
plt.show()
下面是一个适用于Bokeh的完整脚本
import pandas as pd
from bokeh.io import output_file, show
from bokeh.plotting import figure
output_file("signal.html")
data = pd.DataFrame(dict(
time=[1, 1.1, 1.2, 1.5, 1.8],
down=[19371, None, None, 38175, None],
up=[None, 36823, 91046, None, 47722]
))
data['mapped'] = data.up.isnull()
# This computes the "step" data
x, y = [], []
prev = -1
for index, row in data.iterrows():
if row.mapped != prev and prev>=0:
x.append(row.time)
y.append(prev)
x.append(row.time)
y.append(int(row.mapped))
prev = int(row.mapped)
p = figure()
p.line(x=x, y=y, legend="signal")
p.circle(x=data.time, y=data.mapped, legend="signal")
p.legend.click_policy="hide"
show(p)
这将产生以下带有交互式图例的Bokeh图:
正如我在评论中宣布的,以下是我目前使用的代码:
import timeit
start_time = timeit.default_timer()
import io
import os
import sys
import math
import pandas
from bokeh.io import output_file, show
from bokeh.plotting import figure
output_file("signal.html")
def fillSquareWave(xi, downi, upi):
resultx = [0,]
resulty = [0,]
lasty = 0
for x, down, up in zip(xi, downi, upi):
if (math.isnan(down)) and (math.isnan(up)):
# no dropna() at pandas level, since it'd drop if EITHER is a nan (we only drop if BOTH are)
pass
else:
# append extra point
resultx.append(x)
resulty.append(lasty)
# append real, current point
resultx.append(x)
if (not math.isnan(down)) and (math.isnan(up)):
resulty.append(0)
lasty = 0
elif (math.isnan(down)) and (not math.isnan(up)):
resulty.append(1)
lasty = 1
else:
print("x: ", x, " down: ", down, " up: ", up)
assert(False)
return resultx, resulty
sourcefile = os.path.basename(sys.argv[1])
bothpts = pandas.read_csv(sourcefile, usecols=['Time', 'down', 'up'])
uppts = pandas.read_csv(sourcefile, usecols=['Time', 'up'])
uppts.dropna(inplace=True)
uppts['up'] = 1
downpts = pandas.read_csv(sourcefile, usecols=['Time', 'down'])
downpts.dropna(inplace=True)
downpts['down'] = 0
php = figure()
php.scatter(uppts['Time'], uppts['up'], legend='up',)
php.scatter(downpts['Time'], downpts['down'], legend='down')
xdata, ydata = fillSquareWave(bothpts['Time'], bothpts['down'], bothpts['up'])
php.line(xdata, ydata, legend='overlay')
php.legend.click_policy = "hide"
show(php)
print("Rendered in %.2fs" % (timeit.default_timer() - start_time))
此代码生成的绘图与问题略有不同-它从(0,0)开始绘制,而不是从CSV文件中第一个点的坐标开始绘制
编辑:可以使用以下代码删除多个read\u csv()调用,但执行时间基本不变
bothpts = pandas.read_csv(sourcefile, usecols=['Time', 'down', 'up'])
uppts = copy(bothpts)
del uppts['down']
uppts.dropna(inplace=True)
uppts['up'] = 1
downpts = copy(bothpts)
del downpts['up']
downpts.dropna(inplace=True)
downpts['down'] = 0
问题是关于如何使用Bokeh而不是Matplotlib创建交互式绘图。谢谢。有趣的是,matplotlib对这个确切的用例有很好的解释。然而,我已经非常喜欢Bokeh绘图了,所以我的纯Python解决方案现在必须要做,特别是因为基准测试已经证明它是可以接受的。非常好的答案,Pandas和Bokeh都有很多值得学习的地方,特别是通过给它们相同的图例名来合并多个glyph是可能的。谢谢然而,您的答案有一个很大的缺点-它比我当前的代码慢得多:在我的7700点测试文件中大约是2.4s,而我的大约是1.4s。我怀疑对boolean_map()的7700次调用会伤害到你。我将发布我的代码作为答案,以防感兴趣。很可能,数据大小没有说明,所以我选择了“最简单”的东西。我已经更新了答案,以便它可能更有效。它应该是down.isnull()或up.notnull(),但由于我无法解释的原因,它仍然需要相同的2.4s。哦,好吧。