Вполне возможно, существует уже существующее решение этой проблемы с использованием пакетов Reticulate или RcppCNPy . Тем не менее, я подумал, что было бы полезно показать, как вы можете сделать это на базе R.
Когда вы читаете произвольные двоичные данные в R, используя readBin
, он считывает файл в «сырой» вектор. Это вектор отдельных байтов в файле. Таким образом, вы могли бы сделать:
my_data <- readBin("filename.DAT", "raw", 10e6)
Таким образом, легко получить данные в R. Трудная часть заключается в их интерпретации.
Насколько я могу судить по документам numpy, данные, хранящиеся в вашем DAT, должны записываться как непрерывный блок байтов с порядком байтов в младшем порядке. Таким образом, в вашем файле с указанным форматом у вас должны быть первые 4 байта, представляющие 32-разрядное целое число без знака, следующие два байта, представляющие целое число без знака, и следующие 6 байтов, представляющие 3 16-разрядных целых числа со знаком. Затем этот шаблон будет повторяться каждые 12 байт до конца файла.
Этот формат не используется в R, поэтому для восстановления данных требуется немного усилий. Допустим, вы прочитали свои данные, и это выглядит так:
my_data
# [1] 44 5f 93 e8 34 e6 f1 a9 a1 10 35 2e b0 62 c5 7f b7 fd 61 c7 ef 37 a7 21 45 63
# [27] 04 62 de 57 7b 99 7e 30 d3 ab cb 1c b9 69 d2 a6 c8 8e 88 ca 06 7a bb b1 7a dc
# [53] 70 3f 13 1a 51 85 a9 68
Если вы хотите посмотреть, как выглядят ваши байты в терминах строк данных в вашей таблице, вы можете сделать это:
t(matrix(my_data, nrow = 12))
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
# [1,] 44 5f 93 e8 34 e6 f1 a9 a1 10 35 2e
# [2,] b0 62 c5 7f b7 fd 61 c7 ef 37 a7 21
# [3,] 45 63 04 62 de 57 7b 99 7e 30 d3 ab
# [4,] cb 1c b9 69 d2 a6 c8 8e 88 ca 06 7a
# [5,] bb b1 7a dc 70 3f 13 1a 51 85 a9 68
Это означает, что ваши двоичные данные должны интерпретироваться следующим образом:
# <-----var1--------> <-var2--> <-var3--> <-var4--> <-var5->
# 44 5f 93 e8 | 34 e6 | f1 a9 | a1 10 | 35 2e <- row 1
# b0 62 c5 7f | b7 fd | 61 c7 | ef 37 | a7 21 <- row 2
# 45 63 04 62 | de 57 | 7b 99 | 7e 30 | d3 ab <- row 3
# cb 1c b9 69 | d2 a6 | c8 8e | 88 ca | 06 7a <- row 4
# bb b1 7a dc | 70 3f | 13 1a | 51 85 | a9 68 <- row 5
Итак, если мы сначала создадим фрейм данных из этой матрицы:
df <- as.data.frame(t(matrix(as.numeric(my_data), nrow = 12)))
Теперь мы можем воссоздать наши переменные из известной структуры файла:
# Make our 32-bit numbers
var1 <- df$V1 + 2^8 * df$V2 + 2^16 * df$V3 + 2^24 * df$V4
# Make our 16-bit numbers
var2 <- df$V5 + 2^8 * df$V6
var3 <- df$V7 + 2^8 * df$V8
var4 <- df$V9 + 2^8 * df$V10
var5 <- df$V11 + 2^8 * df$V12
# Interpret our var3, 4 and 5 as signed rather than unsigned
var3 <- ifelse(var3 < 2^15, var3, var3 - 2^16)
var4 <- ifelse(var4 < 2^15, var4, var4 - 2^16)
var5 <- ifelse(var5 < 2^15, var5, var5 - 2^16)
# Store as a data frame
df <- data.frame(var1 = var1, var2 = var2, var3 = var3, var4 = var4, var5 = var5)
Это означает, что мы получаем следующую интерпретацию наших байтов:
df
#> var1 var2 var3 var4 var5
#> 1 3901972292 58932 -22031 4257 11829
#> 2 2143642288 64951 -14495 14319 8615
#> 3 1644454725 22494 -26245 12414 -21549
#> 4 1773739211 42706 -28984 -13688 31238
#> 5 3699028411 16240 6675 -31407 26793
Итак, предполагая, что ваши данные находятся в ТОЧНО указанном вами формате, следующая функция должна извлечь их как фрейм данных:
read_numpy_data <- function(path, max_file_size = 10e6)
{
my_data <- readBin(path, "raw", max_file_size)
df <- as.data.frame(t(matrix(as.numeric(my_data), nrow = 12)))
as_sign <- function(x, y) {(x + 2^8 * y) -> z; ifelse(z < 2^15, z, z - 2^16)}
data.frame(var1 = df$V1 + 2^8 * df$V2 + 2^16 * df$V3 + 2^24 * df$V4,
var2 = df$V5 + 2^8 * df$V6,
var3 = as_sign(df$V7, df$V8),
var4 = as_sign(df$V9, df$V10),
var5 = as_sign(df$V11, df$V12))
}