将列数组转换为交替行

Converting column arrays to alternating rows

来自以下格式...(x1-x27y1-y27 是数字 x,y 坐标,需要移动到单个行,对于每个主题。)

Subj    X   Y
1   x1  y1
1   x2  y2
1   x3  y3
1   x4  y4
1   x5  y5
1   x6  y6
1   x7  y7
1   x8  y8
1   x9  y9
2   x10 y10
2   x11 y11
2   x12 y12
2   x13 y13
2   x14 y14
2   x15 y15
2   x16 y16
2   x17 y17
2   x18 y18
3   x19 y19
3   x20 y20
3   x21 y21
3   x22 y22
3   x23 y23
3   x24 y24
3   x25 y25
3   x26 y26
3   x27 y27

格式如下图:

Subj    X   Y                                                               
1   x1  y1  x2  y2  x3  y3  x4  y4  x5  y5  x6  y6  x7  y7  x8  y8  x9  y9
2   x10 y10 x11 y11 x12 y12 x13 y13 x14 y14 x15 y15 x16 y16 x17 y17 x18 y18
3   x19 y19 x20 y20 x21 y21 x22 y22 x23 y23 x24 y24 x25 y25 x26 y26 x27 y27

我想使用 R 或 MATLAB R2016a 来完成此操作。

这是在 MATLAB R2016b 中执行此操作的一种方法:

in = [repelem(1:3,9).' ...
      strcat(string('x'), string((1:27).')) ...
      strcat(string('y'), string((1:27).'))];

u = unique(in(:,1)); 
out = [u reshape(in(:,2:3).', [], numel(u)).'];

在旧版本中,您可能会使用元胞数组而不是 string 变量(除非 x1...y27 实际上是数字,在这种情况下,常规数组就可以)。

使用concatenation和find(),很简单。这是一个示例代码:

clc;clear;close;

SubjectMatrix=[
1  ,11  ,21;
1  ,12  ,22;
1  ,13  ,23;
1  ,14  ,24;
1  ,15  ,25;
1  ,16  ,26;
1  ,17  ,27;
1  ,18  ,28;
1  ,19  ,29;
2  ,110 ,210;
2  ,111 ,211;
2  ,112 ,212;
2  ,113 ,213;
2  ,114 ,214;
2  ,115 ,215;
2  ,116 ,216;
2  ,117 ,217;
2  ,118 ,218;
3  ,119 ,219;
3  ,120 ,220;
3  ,121 ,221;
3  ,122 ,222;
3  ,123 ,223;
3  ,124 ,224;
3  ,125 ,225;
3  ,126 ,226;
3  ,127 ,227; ];

Subject1=[];
Subject2=[];
Subject3=[];

Matcoor=find(SubjectMatrix(:,1)==1);
for i=1:length(Matcoor)
    Subject1=[Subject1 SubjectMatrix(Matcoor(i),2:3)];%concatenation
end

Matcoor=find(SubjectMatrix(:,1)==2);
for i=1:length(Matcoor)
    Subject2=[Subject2 SubjectMatrix(Matcoor(i),2:3)];%concatenation
end

Matcoor=find(SubjectMatrix(:,1)==3);
for i=1:length(Matcoor)
    Subject3=[Subject3 SubjectMatrix(Matcoor(i),2:3)];%concatenation
end

这里是Matlab上的另一种方式,使用线性索引(假设题目编号为正整数):

data = [repelem([1 2 4],4).' randi(50,12,2)]; % some data...
%% code start here: %%
unsubj = unique(data(:,1)); % get unique subjucts numbers
coordsN = numel(data(:,2:end))/numel(unsubj); % no. data values per subject
% linear indices for the data
coord_ind = bsxfun(@plus,unsubj,0:max(unsubj):coordsN*max(unsubj)-1).';
output = zeros(max(unsubj),coordsN); % initialize the output
output(coord_ind(:)) = data(:,2:3).'; % fill the output matrix
subjT(unsubj) = unsubj; % make the first column
output = [subjT.' output]; % add the subect column

此解决方案的优势在于它还可以将不连续的行号作为主题的输入(如上面代码中的示例所示)。

R中,您可以使用data.table重塑。这是最灵活的方法,因为不同 Subj 的数量不受限制,每个 Subj 的坐标数量也不受限制。

library(data.table)
DTM <- melt(DT, id.var = "Subj")
dcast(DTM, Subj ~ rowid(Subj, variable) + variable, value.var = "value")
#   Subj 1_X 1_Y 2_X 2_Y 3_X 3_Y 4_X 4_Y 5_X 5_Y 6_X 6_Y 7_X 7_Y 8_X 8_Y 9_X 9_Y
#1:    1  x1  y1  x2  y2  x3  y3  x4  y4  x5  y5  x6  y6  x7  y7  x8  y8  x9  y9
#2:    2 x10 y10 x11 y11 x12 y12 x13 y13 x14 y14 x15 y15 x16 y16 x17 y17 x18 y18
#3:    3 x19 y19 x20 y20 x21 y21 x22 y22 x23 y23 x24 y24 x25 y25 x26 y26 x27 y27

首先,DT从宽格式重塑为长格式,这样所有坐标都是 在 value 列中。 variable 列包含 "X" 和 "Y" 以指示从中获取值的原始列名称。

然后,熔融数据DTM从长到宽重新整形。因此,一个行索引是动态创建的,它对应于原始 DT 中每个 Subj 的行号。列首先按此行索引排序,然后按变量名排序,以确保 XY 值交替出现。

如果每个组的坐标数不同,则缺失的列值将用 NA 填充。

这可以合并为一行代码:

dcast(melt(DT, id.var = "Subj"), Subj ~ rowid(Subj, variable) + variable, value.var = "value")

请注意,还有另一种使用 matrix 的方法,但这需要更多的代码行并且不太灵活,因为所有 Subj.[=27 的坐标对数量必须相同=]


数据

DT <- structure(list(Subj = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
3L), X = c("x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", 
"x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", 
"x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27"
), Y = c("y1", "y2", "y3", "y4", "y5", "y6", "y7", "y8", "y9", 
"y10", "y11", "y12", "y13", "y14", "y15", "y16", "y17", "y18", 
"y19", "y20", "y21", "y22", "y23", "y24", "y25", "y26", "y27"
)), .Names = c("Subj", "X", "Y"), row.names = c(NA, -27L), class = c("data.table", 
"data.frame"))