2016-06-13 12 views
5

発生率マトリックスを作成したいと思います。
私は次のように、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) 

問題は、上記の例のように、特定の列に1を埋め込む方法がわかりません。
私は正しい方法でいるかどうかもわかりません。

私が助けてくれる提案はありますか?

ありがとうございます!

+0

DataFramesパッケージの 'ModelFrame()'と 'ModelMatrix()'関数を調べましたか?彼らはあなたが必要とする機能を持っている可能性があります。スパース行列を作成するためのsparse()関数もあります(これは作成しようとしているものです)。それはここではうまくいくが、実装するのが少し複雑だ。 –

+1

インシデンス行列の意図的なx = 2とy = 2の同じ列ですか? –

+0

IntやBoolのような単一の特定の型のインシデンス行列を保持し、文字列であるラベルに混在させないことは、型推論と効率の方がずっと優れています。 –

答えて

2

NamedArraysは、行と列の両方に名前を付けることができ、この問題の請求書に適合しているようなきれいなパッケージです。データがdata.csvであるとし、ここではそれについて移動する一つの方法は、(Pkg.add("NamedArrays")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が必要な場合は、同様のトリックを適用する必要があります。

---------- ---------- UPDATE

値の列、すなわち、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 
+0

ありがとうございました。 UPDATEバージョンが探していたものです。 列と行の名前を使用せずに、行列だけを印刷する方法はありますか? ありがとう! –

+0

NamedArraysには通常の配列が使用されています。つまり、ほとんどオーバーヘッドをかけずに通常のMatrixに変換できます。使用: 'array(narr)'。 –

+0

NamedArraysを使用しないで、 'rows'、' cols'変数に固執して普通のArrayを作ることもできます。このルートに行くと、何らかのルックアップテーブル(またはDict)が必要になりますが、このルートを使用するには 'narr = zeros(Int、length(rows)、length(cols) –

1

をここで私は、回帰分析のためのカテゴリ変数のうち、スパース行列を作成するために使用し、何かに若干のばらつきがあります。この機能には、ニーズに合わせてさまざまなコメントとオプションが含まれています。注:書かれているように、xとyの "2"と "21"の出現を別々に扱います。ダン・ゲッツの素敵なレスポンスより、ネーミングとアピアランスがはるかにエレガントです。ここでの主な利点は、データが巨大であれば、疎行列でも動作するため、記憶領域と計算時間を削減するのに役立ちます。

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 
+0

助けてくれてありがとう 唯一の問題は、2行目のように最初の行に値が重複しないようにしたいということです。 –

+0

@GersonOliveiraJuniorよろしくお願いします。あなたが探しているものをもっと見つけてください。これは私が別のプロジェクトから得たコードのスニペットです。役に立つと思ったらそこに投げ捨てると思いました。 –

関連する問題