我正在尝试从矩阵中“按列分组”数据。
从数据库中提取数据,矩阵如下所示:
'2012-04-26' 'USD' 'BRL' [ 1.8894]
'2012-04-26' 'USD' 'IDR' [ 9185]
'2012-04-26' 'USD' 'INR' [ 52.5350]
'2012-04-26' 'USD' 'MXN' [ 13.2337]
'2012-04-26' 'USD' 'PEN' [ 2.6505]
'2012-04-26' 'USD' 'SGD' [ 1.2412]
'2012-04-26' 'USD' 'TRY' [ 1.7643]
'2012-04-27' 'USD' 'BRL' [ 1.8846]
'2012-04-27' 'USD' 'IDR' [ 9189]
'2012-04-27' 'USD' 'INR' [ 52.5600]
'2012-04-27' 'USD' 'MXN' [ 13.0147]
'2012-04-27' 'USD' 'PEN' [ 2.6395]
'2012-04-27' 'USD' 'SGD' [ 1.2385]
'2012-04-27' 'USD' 'TRY' [ 1.7600]
(这是一个单元格数组)
我想要做的是按日期(第1行)对所有数据进行分组,然后为每个值分配一列,如下所示:
'2012-04-26' [ 1.8894] [ 9185] [ 52.5350] [ 13.2337] [ 2.6505] [ 1.2412] [ 1.7643]
'2012-04-27' [ 1.8846] [ 9189] [ 52.5600] [ 13.0147] [ 2.6395] [ 1.2385] [ 1.7600]
其中每一行代表货币对(USD / BRL,USD / IDR,USD / INR,......)
请注意,对于每个日期,它们在提取的数据中与行数(货币对)完全相同。
在Matlab中有一种优雅(快速)的方法吗?
谢谢,
答案 0 :(得分:2)
鉴于您强调速度在问题中很重要,我提出以下解决方案:
%# Build an example cell array
D = cell(6, 4);
for t = 1:3; D{t, 1} = '2012-04-26'; D{t, 2} = 'A'; D{t, 3} = 'A'; D{t, 4} = t; end;
for t = 4:6; D{t, 1} = '2012-04-27'; D{t, 2} = 'A'; D{t, 3} = 'A'; D{t, 4} = t; end;
%# My Solution
X = [datenum(D(:, 1), 'yyyy-mm-dd'), cell2mat(D(:, 4))];
[UniqueDate, ~, Index] = unique(X(:, 1));
NumObsPerDay = sum(Index == 1);
NumDay = length(UniqueDate);
Soln = [UniqueDate, reshape(X(:, 2), NumObsPerDay, NumDay)'];
在第一行中,我将重要的数据提取到数字数组中。操作数字阵列比单元阵列快得多,因为单个元素占用的内存要少得多。为了处理日期字符串,我将在第一步中将它们转换为matlab numerical date format。如果您打算多使用Matlab,我建议您熟悉数字日期格式,因为它比使用字符串更灵活 - 例如,您可以执行任何类型的算术,您希望使用数字日期格式。
在第二行,我得到一个唯一的日期列表和一个索引。
在第三和第四行中,我使用索引来获取您拥有数据的天数以及每天的观察数量。 注意:第NumObsPerDay = sum(Index == 1);
行隐含地假设您每天的观察数量(即其他货币)相同。但是,你在问题中说明情况就是这样,所以我带你去接受你的话: - )
在第五行中,我创建了一个具有所需格式的数字矩阵。第一列是第2行中获得的唯一日期向量,我通过重新整形X
中的数据获得了剩余的列。 注意:此行隐含地假设您的单元格数组中的货币排序每天都相同。同样,我已经做了这个假设,因为它在您的示例数据中是正确的,并且您表示您想要一个快速解决方案。
最后注意:如果违反了上述任何一项假设,则此代码将失败,否则您的数据将会混淆。换句话说,如果您确定所有数据都符合您提供的样本,那么此解决方案应该起作用,并且也应该很快。但如果你不确定,那对你来说这不是一个好的解决方案。
ps如果您想再次以字符串格式查看日期,只需使用datestr(Soln(:, 1), 'yyyy-mm-dd');