将方波边缘时间戳数据转换为适合绘图的数据

时间:2017-06-14 12:59:58

标签: pandas bokeh

这是我正在使用的数据的示例:

enter image description here

它是布尔方波的描述,具有以下特征:

  • " Down"中的数字列是随机整数,但总是绘制为零
  • Up列中的数字也是随机整数,但总是绘制为1
  • 大部分时间," Up"和" Down"经常交替,但偶尔,额外的" Down"或" Up"可以在场。
  • 转换之间的延迟是不规则的 - "时间"列应该被认为是随机的,但是顺序的(已排序的)。

这里是我之后的散景表示:enter image description here

需要查看原始点(包括重复的点,如t = 1.2)和线叠加。

我的理解是最简单的方法是在每对之间插入一个点,y值是前一个点的上/下值和下一个点的x值。然后,在散景中,将原始数据绘制为散射,将Data + InterpolatedData绘制为线图。这意味着情节中有两个不同的字形,我宁愿避免(能够使用新的legend.click_policy ="隐藏"),但是可以容忍。

使用常规python代码很容易实现插值,但我更喜欢用pandas找到一种方法来实现代码一致性。大熊猫是这种插值的合适工具吗?

最佳解决方案将导致散景中的单个字形。我愿意牺牲性能来实现这一目标。 一个好的解决方案用pandas代码替换我的纯python代码。

3 个答案:

答案 0 :(得分:3)

以下是适用于Bokeh的完整脚本。

{
  "channelData": {
    "message": {
      "chat": {
        "all_members_are_administrators": true,
        "id": -219911672,
        "title": "jlarky-dev",
        "type": "group"
      },
      "date": 1493246056,
      "from": {
        "first_name": "Test",
        "id": 107390199
      },
      "message_id": 100,
      "text": "test"
    },
    "update_id": 66470785
  },
  "channelId": "telegram",
  "conversation": {
    "id": "-219911672",
    "isGroup": true,
    "name": "jlarky-dev"
  },
  "entities": [
    {
      "mentioned": {
        "id": "JLarkyTestBot",
        "name": "jlarky_test"
      },
      "text": "JLarkyTestBot",
      "type": "mention"
    }
  ],
  "from": {
    "id": "107390199"
  },
  "id": "KxBlE8JsLfg",
  "recipient": {
    "id": "JLarkyTestBot",
    "name": "jlarky_test"
  },
  "serviceUrl": "https://telegram.botframework.com",
  "text": "test",
  "timestamp": "2017-04-26T22:34:17.4109674Z",
  "type": "message"
}

这会产生以下带有交互式图例的散景图:

enter image description here

答案 1 :(得分:0)

这应该让你开始。请注意,matplotlib是直接使用的,而不是pandas(实际上使用matplotlib)来绘制。

import pandas as pd
import matplotlib.pyplot as plt

使用pandas映射数据:

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)

Output

绘制数据:

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()

Graph Example

答案 2 :(得分:0)

正如评论中所述,这是我目前正在使用的代码:

    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_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