【问题标题】:Converting column arrays to alternating rows将列数组转换为交替行
【发布时间】:2017-02-26 07:46:47
【问题描述】:

从以下格式...(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 中:transpose 然后reshape 然后再次转置。
  • 您的问题仍未解决,即您尚未接受其中一个答案。这是否意味着没有一个答案能解决您的问题?
  • 如果一个/一些答案对您有帮助,请接受\upvote它。

标签: r matlab matrix coordinates reshape


【解决方案1】:

这是在 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 实际上是数字,在这种情况下,可以使用常规数组)。

【讨论】:

  • 是的... x1 - x27, y1-y27 是实际的 X、Y 坐标,我需要根据第一列在单行中移动。
  • @Roopali 这是应该出现在问题本身中的信息。您还应该提及您可以使用的 MATLAB 版本。 1 的点数总是与 23 的点数相同,对吧?请edit该问题并将其包含在内。
  • @Roopali 仍然缺少一些信息。无论如何-这段代码不能解决您的问题吗? (忽略in = ...,我只用它来生成输入。)
【解决方案2】:

这是 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

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

【讨论】:

    【解决方案3】:

    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 的坐标对的数量必须相同。


    数据

    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"))
    

    【讨论】:

      【解决方案4】:

      使用连接和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
      

      【讨论】:

      • 当有 20 个组而不仅仅是 3 个时会发生什么...?复制粘贴代码表明设计不佳。
      • 使用for循环,就这么简单
      • 好吧,如果您建议使用嵌套的for 循环,为什么要拐弯抹角呢?只要把它放在你的答案中就可以了:)
      • 循环中动态增长的数组是一场时间灾难。每次更新数组时,它都会将其写入副本,附加新值并删除原始值。这可以很容易地将您的代码减慢 100 倍或更多,尤其是对于大型数组。请不要这样做,只需先将您的数组初始化为最终大小。
      猜你喜欢
      • 2023-01-05
      • 2018-11-02
      • 2023-03-14
      • 2020-08-30
      • 1970-01-01
      • 2018-03-23
      • 1970-01-01
      • 1970-01-01
      • 2021-04-18
      相关资源
      最近更新 更多