如何在Julia中创建关联矩阵

时间:2016-06-13 19:43:10

标签: matrix julia

我想创建一个关联矩阵 我有一个包含3列的文件,例如:

id x  y   
A  22   2   
B   4  21   
C  21 360   
D  26   2   
E  22  58   
F   2 347   

我想要一个矩阵(没有col和行名称):

  2 4 21 22 26 58 347 360   
A 1 0  0  1  0  0   0   0   
B 0 1  1  0  0  0   0   0   
C 0 0  1  0  0  0   0   1   
D 1 0  0  0  1  0   0   0   
E 0 0  0  1  0  1   0   0   
F 1 0  0  0  0  0   1   0   

我已经启动了代码:

haps = readdlm("File.txt",header=true)      
hap1_2 = map(Int64,haps[1][:,2:end])    
ID = (haps[1][:,1])                      
dic1 = Dict()

for (i in 1:21)
    dic1[ID[i]] = hap1_2[i,:]
end

X=[zeros(21,22)];       #the original file has 21 rows and 22 columns 
X1 = hcat(ID,X)

现在的问题是我不知道如何用特定列中的1s填充矩阵,如上例所示。
我也不确定我是否走在正确的路上。

任何可以帮助我的建议??

谢谢!

2 个答案:

答案 0 :(得分:2)

NamedArrays是一个整洁的包,允许命名行和列,似乎适合这个问题的账单。假设数据位于data.csv,以下是一种方法(使用NamedArrays安装Pkg.add("NamedArrays")):

data,header = readcsv("data.csv",header=true);
# get the column names by looking at unique values in columns
cols = unique(vec([(header[j+1],data[i,j+1]) for i in 1:size(data,1),j=1:2]))
# row names from ID column
rows = data[:,1]

using NamedArrays
narr = NamedArray(zeros(Int,length(rows),length(cols)),(rows,cols),("id","attr"));
# now stamp in the 1s in the right places
for r=1:size(data,1),c=2:size(data,2) narr[data[r,1],(header[c],data[r,c])] = 1 ; end

现在我们有了(请注意我转置narr以获得更好的打印输出):

julia> narr'
10x6 NamedArray{Int64,2}:
attr ╲ id │ A  B  C  D  E  F
──────────┼─────────────────
("x",22)  │ 1  0  0  0  1  0
("x",4)   │ 0  1  0  0  0  0
("x",21)  │ 0  0  1  0  0  0
("x",26)  │ 0  0  0  1  0  0
("x",2)   │ 0  0  0  0  0  1
("y",2)   │ 1  0  0  1  0  0
("y",21)  │ 0  1  0  0  0  0
("y",360) │ 0  0  1  0  0  0
("y",58)  │ 0  0  0  0  1  0
("y",347) │ 0  0  0  0  0  1

但是,如果需要DataFrames,则应采用类似的技巧。

----------更新----------

如果值的列应该被忽略,即x = 2且y = 2,则两者都应为列2设置1,则代码变为:

using NamedArrays
data,header = readcsv("data.csv",header=true);
rows = data[:,1]
cols = map(string,sort(unique(vec(data[:,2:end]))))
narr = NamedArray(zeros(Int,length(rows),length(cols)),(rows,cols),("id","attr"));
for r=1:size(data,1),c=2:size(data,2) narr[data[r,1],string(data[r,c])] = 1 ; end

,并提供:

julia> narr
6x8 NamedArray{Int64,2}:
id ╲ attr │   2    4   21   22   26   58  347  360
──────────┼───────────────────────────────────────
A         │   1    0    0    1    0    0    0    0
B         │   0    1    1    0    0    0    0    0
C         │   0    0    1    0    0    0    0    1
D         │   1    0    0    0    1    0    0    0
E         │   0    0    0    1    0    1    0    0
F         │   1    0    0    0    0    0    1    0

答案 1 :(得分:1)

这是我用于从回归分析的分类变量中创建稀疏矩阵的某些内容的略微变化。该功能包括各种评论和选项,以满足您的需求。注意:如上所述,它将x和y中“2”和“21”的外观视为单独的。命名和外观远不如Dan Getz的好评。这里的主要优点是它适用于稀疏矩阵,因此如果您的数据很大,这将有助于减少存储空间和计算时间。

function OneHot(x::Array, header::Bool)
    UniqueVals = unique(x)
    Val_to_Idx = [Val => Idx for (Idx, Val) in enumerate(unique(x))] ## create a dictionary that maps unique values in the input array to column positions in the new sparse matrix.
    ColIdx = convert(Array{Int64}, [Val_to_Idx[Val] for Val in x])
    MySparse = sparse(collect(1:length(x)),  ColIdx, ones(Int32, length(x)))
    if header
        return [UniqueVals' ; MySparse]  ## note: this won't be sparse
        ## alternatively use return (MySparse, UniqueVals) to get a tuple, second element is the header which you can then feed to something to name the columns or do whatever else with
    else
        return MySparse ## use MySparse[:, 2:end] to drop a value (which you would want to do for categorical variables in a regression)
    end
end

x = [22, 4, 21, 26, 22, 2];
y = [2, 21, 360, 2, 58, 347];

Incidence = [OneHot(x, true) OneHot(y, true)]

7x10 Array{Int64,2}:
 22  4  21  26  2  2  21  360  58  347
  1  0   0   0  0  1   0    0   0    0
  0  1   0   0  0  0   1    0   0    0
  0  0   1   0  0  0   0    1   0    0
  0  0   0   1  0  1   0    0   0    0
  1  0   0   0  0  0   0    0   1    0
  0  0   0   0  1  0   0    0   0    1