pandas.DataFrame 转成 numpy.array 以及 C++ 的二进制文件

作者: , 共 2940 字 , 共阅读 0

1、C++的二进制数据

首先任意定义一个结构,注意不要用 std::string 非平凡布局的变量,用 char[] 代替:

struct KLine
{
    char code[32];         //!< @brief 代码。如600030.SH。
    int date;              //!< @brief 日期,格式yyyymmdd
    int time;              //!< @brief 开始时间,格式hhmmss
    float open;            //!< @brief 开盘价
    float high;            //!< @brief 最高价
    float low;             //!< @brief 最低价
    float close;           //!< @brief 收盘价
    float volume;          //!< @brief 成交量。单位:万元。
    float value;           //!< @brief 成交额。单位:万元。
    float vwap;            //!< @brief 均价
    int ret;                //!< @brief 涨跌幅
};  

然后使用fwrite写入到二进制文件,其中第二个 size 参数为单个元素的大小,第三个参数为元素个数:

KLine klines[1024];

FILE* file = fopen("./klines.bin", "wb");
fwrite(klines, sizeof(KLine), sizeof(klines) / sizeof(KLine), file);

再从文件读入,简单使用fread即可,返回值是读入元素的个数:

KLine klines[1024];

FILE* file = fopen("./klines.bin", "rb");
size_t count = fread(klines, sizeof(KLine), sizeof(klines) / sizeof(KLine), file);

2、Python numpy 数据与二进制数据

Python 的 numpy 要处理二进制数据,需要先定义和 C++一样的数据类型:

import numpy as np

kline_dtype = np.dtype([
    ("code", "|S32"),
    ("date", np.int32),
    ("time", np.int32),
    ("open", np.float32),
    ("high", np.float32),
    ("low", np.float32),
    ("close", np.float32),
    ("volume", np.float32),
    ("value", np.float32),
    ("vwap", np.float32),
    ("ret", np.float32),
])

然后就可以用 np.memmap 直接从二进制文件读取一个数据了(如果读取数据且不会修改,这种方法最好):

klines = np.memmap("./klines.bin", dtype=kline_dtype, mode="r")

如果将 mode 修改为 w ,在该数据上做的修改,还会被直接同步到文件,不需要手工干预。如果只想从文件读取数据进行修改,不想要和文件的关联,直接用 fromfile (和下面的 tofile 对应):

klines = np.fromfile("./klines.bin", dtype=kline_dtype)

要将 numpy 数据写到二进制文件也很简单,使用 tofile 函数即可:

klines.tofile("./klines.bin")

3、Python Pandas 保存为 C++可处理的二进制文件

Pandas 的 DataFrame 要保存为 C++可处理的二进制文件,需要先用to_records转为 numpy 数据,再用 tofile 函数保存。

column_dtypes = {
    key: ds[0]
    for key, ds in kline_dtype.fields.items()
}
data = df.to_records(index=False, column_dtypes=column_dtypes)
data.tofile("./klines.bin")

4、numpy.dtype 详解

上面可以看到, python 处理和 C++互联互通的二进制数据,最核心的就是定义数据结构 np.dtype。np.dtype 有三种大的类型:

  • 内置类型,比如 np.float64, np.int32 等等。
  • 一位数组或多维矩阵,比如np.dtype(np.int32, (12, 24))
  • 更复杂的数据结构,比如上面的kline_dtype,它可以嵌套包含所有数据类型。

它的通用属性有:

  • dtype.itemsize :返回该类型的空间占用大小,比如 float64 是 8 , int32 是 4。
  • dtype.byteorder :字节序;和 C++混用时,不需要管。

内置类型有下面属性,这些属性对所有类型都可以用,但内置类型的返回值才有意义:

  • dtype.name
  • dtype.type
  • dtype.kind :一个字节的标识符,比如float都是f
  • dtype.char :一个字节的标识符,比 kind 分得更细,比如float32ffloat64d
  • dtype.str :该类型的字符串表示,比如默认的float32<f4

数组矩阵类型,有属性:

  • dtype.subdtype :数组里元素的类型和元素大小的二元组。
  • dtype.shape :数组或矩阵的大小。

复杂数据结构的属性:

  • dtype.names :成员的名字列表。
  • dtype.fields :{name: (subdtype, offset)}的映射,其中 subdtype 是成员类型, offset 是该成员数据相对于起始点的偏移位置。

Q. E. D.

类似文章:
编程 » pandas, python
一个最直接的方法如下,最后得到的s2就是一个普通的pandas.DataFrame,可以继续处理:
编程 » Python, numpy
numpy 的一维向量:
编程 » Python, numpy
今天写 Python 代码时遇到一个恶心的 bug ,花了好一会才定位和搞清楚。我的目标是寻找第一个非 NAN 的数的位置(其中 array 是一个 numpy 向量),很自然有下面实现:
Python 数据分析工具 pandas 中以 DataFrame 和 Series 作为主要的数据结构。
编程 » C++
假设在 C++里有一个数据结构:
编程 » C++, Python, 并行计算
我们知道, Python 程序有全局锁,任何时候都只有一个 Python 语句在执行。在 Python 中,这通过全局的 GIL 锁来控制。当 C++和 Python 混合编程,且使用多线程时,也必须考虑到 GIL 锁(单线程无需考虑)。
在 Python 中操作文件或字符串时,有时候会碰到 UnicodeDecodeError 异常:
Python 提供很多语法糖,用起来非常方便。@dataclass 就是其中之一。
编程 » Python
在 Python3 以上,通常说的字符串是指unicode字符串,以下将不再重复强调。
编程 » C++, folly
folly::fbstring是一个完全兼容std::string的类,可以做到无缝替换,而且性能更高。其代码参见https://github.com/facebook/folly/blob/master/folly/FBString.h
东郊森林公园分为两个很大的区域:
命令行参数的初步说明,请参考argparse 模块用法实例详解,写的很清晰而详细。