2014-10-28 3 views
3

У меня есть файл csv/log из 35 = S (Quote messages; «Tag = Value»), и мне нужно извлечь ставки в правильный CSV-файл для сбор данных. Это не строго связано с FIX, это скорее связанный с R вопрос о том, как очистить набор данных.Преобразование формата сообщения FIX («Tag = Value») в CSV

Необработанные сообщения выглядеть примерно так:

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, но мне интересно, если я могу сделать это в R. В настоящее, моя самая большая задача - добраться до промежуточной таблицы. От промежуточного к финальному столу я подумал об использовании R с пакетом tidyr, в частности, функции «отдельно». Если кто-нибудь может предложить лучшую логику, я буду очень признателен!

+0

Можете ли вы пояснить, насколько обширны эти записи? Сколько столбцов и строк данных CSV? – vpipkt

+1

10000 строк и столбцов могут быть более 20, зависит от типа сделки. Это выше всего лишь фрагмент, чтобы получить точку в – fabiog

ответ

4

Другая возможность. Начнем с той же scan как @Andrie, но и использовать аргументы strip.white и na.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)] 

Затем используйте colsplit и dcast из reshape2 пакета:

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, вы можете установить convert = TRUE в spread.

+0

Ничего себе, это выглядит интересно, будет проверяться и возвращаться! Я знал, что ребята Ран видели этот вопрос раньше, спасибо Хенрик! – fabiog

+0

@ Хенрик Могу я попросить одолжение? Не могли бы вы объяснить, как 'ave (d1 $ x, d1 $ x, FUN = seq_along)' создает переменную группировки? Я хотел бы знать, как эта линия работает. – jazzurro

+0

@jazzurro, From '? Ave':« Подмножества x [] усредняются, , где каждое подмножество состоит из этих наблюдений с одинаковыми уровнями факторов. », С по умолчанию« FUN », который является« средним ». В этом случае его можно охарактеризовать как «применить функцию« FUN », здесь« FUN = seq_along », в подмножествах' d1 $ x', где каждое подмножество состоит из тех наблюдений с одинаковыми уровнями факторов, которые определены группировкой переменная 'd1 $ x'. 'ave' индексирует результат в соответствии с порядком исходного вектора. – Henrik

4

EDITED. Полное решение только с использованием базовых функций 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 
+0

. Я не уверен, что это работает, я бы ожидал увидеть 3 переменных для каждого тега, скажем, $ '642' [1]" 0.000145 "," "," " – fabiog

+1

Правильно, поэтому я говорю, что у вас есть вам придется сделать дополнительную работу, чтобы попасть в матрицу, в основном, добавив NAs, если это необходимо. – Andrie

+0

@fabiog Ответ отредактирован. – Andrie

 Смежные вопросы

  • Нет связанных вопросов^_^