【问题标题】:Convert FIX message format ("Tag=Value") into CSV将 FIX 消息格式(“Tag=Value”)转换为 CSV
【发布时间】:2014-12-23 22:40:39
【问题描述】:

我有一个 35=S(引用消息;“标签=值”)的 csv/日志文件,我需要将费率提取到适当的 CSV 文件中以进行数据挖掘。这与 FIX 无关,更多的是关于如何清理数据集的 R 相关问题。

原始消息如下所示:

190=1.1204 ,191=-0.000029,193=20141008,537=0        ,631=1.12029575,642=0.000145,10=56
190=7.20425,191=0.000141 ,537=0       ,631=7.2034485,10=140        ,            ,
190=1.26237,191=0        ,537=1       ,10=068       ,              ,            ,

我首先需要得到一个看起来像这样的中间数据集,其中相同的标签是对齐的。

190=1.1204 ,191=-0.000029,193=20141008,537=0,631=1.12029575,642=0.000145,10=56
190=7.20425,191=0.000141 ,            ,537=0,631=7.2034485 ,            ,10=140
190=1.26237,191=0        ,            ,537=1,              ,            ,10=068

这又需要转换成这个:

190    ,191      ,193     ,537,631       ,642     ,10
1.1204 ,-0.000029,20141008,0  ,1.12029575,0.000145,56
7.20425,0.000141 ,        ,0  ,7.2034485 ,        ,140
1.26237,0        ,        ,1  ,          ,        ,068

我正在使用 awk 开发一个 bash 脚本,但我想知道我是否可以在 R 中做到这一点。目前,我最大的挑战是到达中间表。 从中间到决赛桌,我想到了将 R 与 tidyr 包一起使用,特别是功能“分离”。如果有人能提出更好的逻辑,我将不胜感激!

【问题讨论】:

  • 您能说明一下这些记录的范围有多大吗? CSV 数据有多少列和多少行?
  • 10000 行和列可能超过 20,具体取决于交易类型。上面这只是一个sn-p来说明问题

标签: r string bash fix-protocol tidyr


【解决方案1】:

另一种可能性。从与@Andrie 相同的scan 开始,但也使用参数strip.whitena.strings

x <- scan(text = "190=1.1204 ,191=-0.000029,193=20141008,537=0        ,631=1.12029575,642=0.000145,10=56
190=7.20425,191=0.000141 ,537=0       ,631=7.2034485,10=140        ,            ,
190=1.26237,191=0        ,537=1       ,10=068       ,              ,            ,",
           sep = ",",
           what = "character", 
           strip.white = TRUE,
           na.strings = "")

# remove NA
x <- x[!is.na(x)]

然后使用来自reshape2package 的colsplitdcast

library(reshape2)

# split 'x' into two columns
d1 <- colsplit(string = x, pattern = "=", names = c("x", "y")) 

# create an id variable, needed in dcast
d1$id <- ave(d1$x, d1$x, FUN = seq_along)   

# reshape from long to wide
d2 <- dcast(data = d1, id ~ x, value.var = "y")

#   id  10     190       191      193 537      631      642
# 1  1  56 1.12040 -0.000029 20141008   0 1.120296 0.000145
# 2  2 140 7.20425  0.000141       NA   0 7.203449       NA
# 3  3  68 1.26237  0.000000       NA   1       NA       NA

因为你提到了tidyr

library(tidyr)
d1 <- separate(data = data.frame(x), col = x, into = c("x", "y"), sep = "=")
d1$id <- ave(d1$x, d1$x, FUN = seq_along)
spread(data = d1, key = x, value = y)
#   id  10     190       191      193 537        631      642
# 1  1  56  1.1204 -0.000029 20141008   0 1.12029575 0.000145
# 2  2 140 7.20425  0.000141     <NA>   0  7.2034485     <NA>
# 3  3 068 1.26237         0     <NA>   1       <NA>     <NA>

这会将值保留为character。如果要numeric,可以在spread中设置convert = TRUE

【讨论】:

  • 哇,看起来很有趣,将测试并恢复!我知道 R 人以前见过这个问题,谢谢 Henrik!
  • @Henrik 我能帮个忙吗?您能解释一下ave(d1$x, d1$x, FUN = seq_along) 如何创建分组变量吗?我想知道这条线是如何工作的。
  • @jazzurro,来自?ave:“x[] 的子集是平均的,其中每个子集由具有相同因子水平的那些观察组成。”,默认为 FUN,即 @ 987654338@。在这种情况下,它可以描述为“在d1$x 的子集上应用函数FUN,此处为FUN = seq_along,其中每个子集由具有相同因子水平的观察组成,由分组变量d1$x 定义”。 ave按照原向量的顺序索引结果。
  • @Henrik 非常感谢您的解释。我改组了d1 并检查了ave 行的行为。现在我明白你的意思了。由于 id 序列的顺序是完美的(七个 1、五个 2 和四个 3),我看不到发生了什么;我认为 ave 行正在分配类似于组变量的东西。傻我。感谢您抽出宝贵时间。
【解决方案2】:

已编辑。仅使用基本 R 函数的完整解决方案:

dat <- scan(sep=",", what="character", text="190=1.1204 ,191=-0.000029,193=20141008,537=0        ,631=1.12029575,642=0.000145,10=56
190=7.20425,191=0.000141 ,537=0       ,631=7.2034485,10=140        ,            ,
190=1.26237,191=0        ,537=1       ,10=068       ,              ,            ,")

dat <- gsub(" ", "", dat)
dat <- dat[dat != ""]

x <- as.data.frame(
  matrix(
    unlist(
      sapply(dat, strsplit, split = "=", USE.NAMES=FALSE)
    ),
    ncol=2, byrow=TRUE
  )
)

z <- unstack(x, V2 ~ V1)

生成的对象是一个命名列表,与您想要的很接近。如果需要,您必须做一些额外的工作才能将其转换为矩阵。

$`10`
[1] "56"  "140" "068"

$`190`
[1] "1.1204"  "7.20425" "1.26237"

$`191`
[1] "-0.000029" "0.000141"  "0"   

....
etc.     

从这里,您只需用适当数量的 NA 值填充列表:

maxLength <- max(sapply(z, length))
sapply(z, function(x)c(as.numeric(x), rep(NA, maxLength - length(x))))

给予:

      10     190       191      193 537      631      642
[1,]  56 1.12040 -0.000029 20141008   0 1.120296 0.000145
[2,] 140 7.20425  0.000141       NA   0 7.203449       NA
[3,]  68 1.26237  0.000000       NA   1       NA       NA

【讨论】:

  • 谢谢。我不确定这是否有效,我希望每个标签都有 3 个变量,例如 $642 [1] "0.000145", "", ""
  • 正确,这就是为什么我说你必须做一些额外的工作才能进入矩阵,主要是通过适当地添加 NA。
  • 很遗憾,这会导致系统崩溃。有 10000 行和大约 20 个字段,R 崩溃。我可能不得不走 bash/awk 路线。
  • @fabiog 如果您愿意使用其他软件,不妨使用 quickfix。
  • @GSee 是的,所有日志都是由 QF/J 创建的,但我无法访问应用程序本身,只能访问日志。我希望我有,那问题就解决了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-26
  • 2021-12-16
  • 2018-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-29
相关资源
最近更新 更多