Matlab 检查单元格中的ismember
我有一个单元格数组(Matlab 检查单元格中的ismember,matlab,compare,cell,Matlab,Compare,Cell,我有一个单元格数组(数据),看起来像这样(这里简称): 我想根据第四列(使用datenum转换的日期)是否与B匹配,填写NaN的第五列 B(也是一个单元格)看起来像这样(为了使示例更有意义,还缩短了很多): 如您所见,日期的第4列在B中并不一致。我试图将NaN添加到第5列,其中B(:,3)和B(:,4)与数据(:,3)和数据(:,4)不匹配 最终产品应类似于: '45.203885' '-90.600123' '119-8001' 733144 '3.3' '45.203885' '-
数据
),看起来像这样(这里简称):
我想根据第四列(使用datenum
转换的日期)是否与B
匹配,填写NaN
的第五列
B
(也是一个单元格)看起来像这样(为了使示例更有意义,还缩短了很多):
如您所见,日期的第4列在B
中并不一致。我试图将NaN
添加到第5列,其中B(:,3)
和B(:,4)
与数据(:,3)
和数据(:,4)
不匹配
最终产品应类似于:
'45.203885' '-90.600123' '119-8001' 733144 '3.3'
'45.203885' '-90.600123' '119-8001' 733147 NaN
'45.203885' '-90.600123' '119-8001' 733150 '9.5'
'45.203885' '-90.600123' '119-8001' 733153 NaN
'45.203885' '-90.600123' '119-8001' 733156 '6.8'
'45.203885' '-90.600123' '119-8001' 733159 NaN
如果data
是一个矩阵,我将只执行以下操作:
data_ind = ismember(data(:,3:4),B(:,3:4),'rows');
data_ind = ismember(strcat(data(:,3),num2str([data{:,4}]')),...
strcat(B(:,3),num2str([B{:,4}]')));
但我不知道怎么用手机。某种形式的cellfun
会起作用吗
sd = size(data,1); %// number of rows of data
sb = size(B,1); %// number of rows of B
[dd bb] = ndgrid(1:sd,1:sb); %// all combinations (row of data, row of B)
cond1 = strcmp(data(dd,3),B(bb,3)); %// test col 3 for all combinations
cond2 = [data{dd,4}].'==[B{bb,4}].'; %// test col 4 for all combinations
cond = reshape(cond1 & cond2, sd, sb); %// combine the two conditions
[ib, id] = max(cond); %// id contains the index of the first 1 (if any) ...
%// ... of each col in cond; and ib is a logical index of the row of that 1
id = id(ib); %// keep only id for which the maximum is 1
data(id,:) = B(ib,:); %// copy matching rows of B into data
data
和B
都包含与其他变量的任何行不匹配的行的示例:
data = {
'45.203885' '-90.600123' '119-8001' 733144 NaN
'45.203885' '-90.600123' '119-8001' 733147 NaN
'45.203885' '-90.600123' '119-8001' 733150 NaN
'45.203885' '-90.600123' '119-8001' 733153 NaN
'45.203885' '-90.600123' '119-8001' 733156 NaN
'45.203885' '-90.600123' '119-8001' 733159 NaN};
B = {
'45.203885' '-90.600123' '119-8001' [733144] '3.3'
'45.203885' '-90.600123' '119-8001' [733150] '9.5'
'45.203885' '-90.600123' '119-8001' [733156] '6.8'
'45.203885' '-90.600123' '169-8001' [833156] '6.8'};
结果:
data =
'45.203885' '-90.600123' '119-8001' [733144] '3.3'
'45.203885' '-90.600123' '119-8001' [733147] [NaN]
'45.203885' '-90.600123' '119-8001' [733150] '9.5'
'45.203885' '-90.600123' '119-8001' [733153] [NaN]
'45.203885' '-90.600123' '119-8001' [733156] '6.8'
'45.203885' '-90.600123' '119-8001' [733159] [NaN]
由于您将只有唯一的ID+datenum组合,因此可以执行以下操作:
data_ind = ismember(data(:,3:4),B(:,3:4),'rows');
data_ind = ismember(strcat(data(:,3),num2str([data{:,4}]')),...
strcat(B(:,3),num2str([B{:,4}]')));
这样做的目的是将第3列和第4列连接成一个字符串,例如
'45.203885' '-90.600123' '119-8001' 733144 NaN
'45.203885' '-90.600123' '119-8001' 733147 NaN
将成为
'119-8001733144'
'119-8001733147'
等等。然后,它将这些字符串从
数据
矩阵与B
矩阵进行比较,以给出索引矩阵。由于所有条目都相同,因此不清楚您对第三列做了什么。另外,您的问题有点让人困惑,您想在数据中使用B
还是在B
中使用data
。可能最快、最直接的方法是使用for
循环:
data = {'45.203885' '-90.600123' '119-8001' 733144 NaN
'45.203885' '-90.600123' '119-8001' 733147 NaN
'45.203885' '-90.600123' '119-8001' 733150 NaN
'45.203885' '-90.600123' '119-8001' 733153 NaN
'45.203885' '-90.600123' '119-8001' 733156 NaN
'45.203885' '-90.600123' '119-8001' 733159 NaN};
B = {'45.203885' '-90.600123' '119-8001' 733144 '3.3'
'45.203885' '-90.600123' '119-8001' 733150 '9.5'
'45.203885' '-90.600123' '119-8001' 733156 '6.8'};
d3 = data(:,3);
d4 = [data{:,4}].';
for i = 1:size(B,1)
data(strcmp(d3,B{i,3})&d4==B{i,4},5) = B(i,5);
end
不要害怕对循环使用。您也可以使用cellfun
执行此操作,但它需要使用eval
它表示下标的赋值维度不匹配。
用于最后一行`数据(数据索引:)的大小为252x5。B的尺寸是190x5,因为它缺少日期。@shizishan我用一种新的方法重写了我的答案。我想现在它可以在一般情况下工作了。strcmp(C1,C2)
syntax+ndgrid
就是这里的问题。不需要ismember
或for
循环。聪明。@chappjc谢谢!有趣的是,在这种情况下,max
的两个输出如何给出所需的两个索引(逻辑形式的列索引,数字形式的行索引)@chappjc:是的,但是可读性呢?(谁知道速度。)并且ndgrid
对于循环来说就像arrayfun
或cellfun
一样,同时使用更多内存。还有@LuisMendo:这个问题是被删除了一段时间还是什么?当@MrAzzaman和我发布我们的时间戳时,它并不在那里,但出于某种原因,时间戳要老得多。很好。如果第四列始终是整数,int2str
可能会更好。如果这些值是十进制的,请注意默认情况下num2str
仅使用“大约4位数字和一个指数(如果需要)”(sprintf('.17g',…)
更安全)。第4列是datenum类型的数字,并且始终是整数,因为没有提供小时/分钟/秒数据。关于int2str
,这一点很好,但是它不会有太大的区别-num2str
如果输入是整数,则返回到int2str
。是的,在检查数字是否为整数时会有一点开销,但从长远来看,这是可以忽略的。加上一个是为了可读性。虽然我很欣赏避免循环所需的技巧,但这并不意味着for循环有时不是最好的解决方案。