Заполните нижнюю матрицу вектором по строке, а не по столбцу - PullRequest
4 голосов
/ 16 марта 2011

Я пытаюсь прочитать в дисперсионно-ковариационной матрице, записанной LISREL в следующем формате в виде простого текста, разделенного пробелами файла:

 0.23675E+01  0.86752E+00  0.28675E+01 -0.36190E+00 -0.36190E+00  0.25381E+01
-0.32571E+00 -0.32571E+00  0.84425E+00  0.25598E+01 -0.37680E+00 -0.37680E+00
 0.53136E+00  0.47822E+00  0.21120E+01 -0.37680E+00 -0.37680E+00  0.53136E+00
 0.47822E+00  0.91200E+00  0.21120E+01

Это на самом деле нижняя диагональная матрица (включая диагональ):

 0.23675E+01  
 0.86752E+00  0.28675E+01 
-0.36190E+00 -0.36190E+00  0.25381E+01
-0.32571E+00 -0.32571E+00  0.84425E+00  0.25598E+01 
-0.37680E+00 -0.37680E+00  0.53136E+00  0.47822E+00  0.21120E+01 
-0.37680E+00 -0.37680E+00  0.53136E+00  0.47822E+00  0.91200E+00  0.21120E+01

Я могу правильно прочитать значения с помощью scan() или read.table(fill=T).

Однако я не могу правильно сохранить вектор считывания в матрице. Следующий код

S <- diag(6)
S[lower.tri(S,diag=T)] <- d

заполняет нижнюю матрицу столбцом, а должна заполнять ее строкой.

Использование matrix() допускает опцию byrow=TRUE, но это заполнит всю матрицу, а не только нижнюю половину (с диагональю).

Возможно ли иметь и то и другое: только заполнить нижнюю матрицу (диагональю) и сделать это по строке?

(у меня отдельная проблема: LISREL использует 'D + 01', в то время как R распознает только 'E + 01' для научной нотации. Можете ли вы изменить это в R, чтобы также принимать 'D'?)

Ответы [ 2 ]

8 голосов
/ 16 марта 2011

Просто прочитайте это в верхнюю треугольную часть, а не в нижнюю:

S <- diag(6)
S[upper.tri(S, diag=TRUE)] <- d
t(S)
1 голос
/ 16 марта 2011

Пакет sem имеет очень хорошую функцию, read.moments(), которая предназначена именно для этого:

foo <- read.moments()
 0.23675E+01  
 0.86752E+00  0.28675E+01 
-0.36190E+00 -0.36190E+00  0.25381E+01
-0.32571E+00 -0.32571E+00  0.84425E+00  0.25598E+01 
-0.37680E+00 -0.37680E+00  0.53136E+00  0.47822E+00  0.21120E+01 
-0.37680E+00 -0.37680E+00  0.53136E+00  0.47822E+00  0.91200E+00  0.21120E+01

foo[upper.tri(foo)] <- t(foo)[upper.tri(foo)]

Это дает вам:

         X1       X2       X3       X4       X5       X6
X1  2.36750  0.86752 -0.36190 -0.32571 -0.37680 -0.37680
X2  0.86752  2.86750 -0.36190 -0.32571 -0.37680 -0.37680
X3 -0.36190 -0.36190  2.53810  0.84425  0.53136  0.53136
X4 -0.32571 -0.32571  0.84425  2.55980  0.47822  0.47822
X5 -0.37680 -0.37680  0.53136  0.47822  2.11200  0.91200
X6 -0.37680 -0.37680  0.53136  0.47822  0.91200  2.11200

EDIT1: Что касается проблемы с scan(), то, что она изначально была напечатана как нижний треугольник, не означает, что вы должны поместить его в нижний треугольник :) Просто поместите его в верхний:

foo <- scan()
 0.23675E+01  
 0.86752E+00  0.28675E+01 
-0.36190E+00 -0.36190E+00  0.25381E+01
-0.32571E+00 -0.32571E+00  0.84425E+00  0.25598E+01 
-0.37680E+00 -0.37680E+00  0.53136E+00  0.47822E+00  0.21120E+01 
-0.37680E+00 -0.37680E+00  0.53136E+00  0.47822E+00  0.91200E+00  0.21120E+01

bar <- matrix(0,6,6)

bar[upper.tri(bar,diag=TRUE)] <- foo

bar[lower.tri(bar)] <- t(bar)[lower.tri(bar)]

EDIT2: Что касается проблемы с нотацией D, если я правильно понимаю, ее можно исправить с помощью первых символов сканирования, gsub от D до E и привести к числовому значению:

foo <- scan(what="character")
 0.23675D+01  
 0.86752D+00  0.28675D+01 
-0.36190D+00 -0.36190D+00  0.25381D+01
-0.32571D+00 -0.32571D+00  0.84425D+00  0.25598D+01 
-0.37680D+00 -0.37680D+00  0.53136D+00  0.47822D+00  0.21120D+01 
-0.37680D+00 -0.37680D+00  0.53136D+00  0.47822D+00  0.91200D+00  0.21120D+01


bar <- matrix(0,6,6)

bar[upper.tri(bar,diag=TRUE)] <- as.numeric(gsub("D","E",foo))

bar[lower.tri(bar)] <- t(bar)[lower.tri(bar)]

bar
...