用 NaN 替换选择性数字
Posted
技术标签:
【中文标题】用 NaN 替换选择性数字【英文标题】:Replacing selective numbers with NaNs 【发布时间】:2014-06-16 21:23:10 【问题描述】:我有八列数据。第 1、3、5 和 7 列包含 3 位数字。第 2、4、6 和 8 列包含 1 和零,分别对应于 1、3、5 和 7。在偶数列中有零的地方,我想将相应的数字更改为 NaN。更简单地说,如果是的话
155 1 345 0
328 1 288 1
884 0 145 0
326 1 332 1
159 0 186 1
然后 884 将替换为 NaN,159、345 和 145 也将替换为其他数字保持不变。我需要使用 NaN 以矩阵形式维护数据。 我知道我可以使用
data(3,1)=Nan; data(5,1)=Nan
等等,但这非常耗时。任何建议都会非常受欢迎。
【问题讨论】:
【参考方案1】:我会将问题拆分为两个矩阵,一个是逻辑掩码,另一个是您的数据。
data = your_mat(:,1:2:end);
valid = your_mat(:,2:2:end);
那么你可以简单地做:
data(~valid)=NaN;
然后您可以通过以下方式重建数据:
your_mat(:,1:2:end) = data;
【讨论】:
【参考方案2】:方法 1
a1 = [
155 1 345 0
328 1 288 1
884 0 145 0
326 1 332 1
159 0 186 1]
t1 = a1(:,[2:2:end])
data1 = a1(:,[1:2:end])
t1(t1==0)=NaN
t1(t1==1)=data1(t1==1)
a1(:,[1:2:end]) = t1
输出 -
a1 =
155 1 NaN 0
328 1 288 1
NaN 0 NaN 0
326 1 332 1
NaN 0 186 1
方法 2
[x1,y1] = find(~a1(:,[2:2:end]))
a1(sub2ind(size(a1),x1,2*y1-1)) = NaN
【讨论】:
+1 表示方法 2,但 Raab70 的答案似乎将主导方法 1。 谢谢,我同意我的方法有点简单,但方法 2 真的很有趣。 同意@DennisJaheruddin! 方法 1 是我需要的。事实上,@Raab70 的回答对我来说稍微简单一些。虽然没有提到,但我只需要 t1 数据,所以方法 2 不是我想要的。谢谢。【参考方案3】:这是一个替代解决方案。您可以通过以下方式使用circshift
。
首先创建与输入矩阵 A 大小相同的偶数列的掩码:
AM = false(size(A)); AM(:,2:2:end) = true;
然后将掩码(A==0)&AM
向左循环移动一个元素,以在奇数列上移动此掩码。
A(circshift((A==0)&AM,[0 -1])) = nan;
注意:我已经搜索过一种单线...我认为这不是一个好方法,但根据我的解决方案,您可以使用以下一种:
A(circshift(bsxfun(@and, A==0, mod(0:size(A,2)-1,2)),[0 -1])) = nan;
bsxfun
的脏东西是在线创建掩码 AM。我使用索引向量的奇数测试,bsxfun
将其扩展到整个矩阵 A。当然,您可以做任何其他事情来创建这个掩码。
【讨论】:
它似乎有效,但我不确定我是否理解您的最后评论。 circshift 方法总是需要一个完整的掩码,对吗? @DennisJaheruddin 确实我不是很清楚。我只是想强调一下,生成掩码的方法(取索引向量的模)不是唯一的,你可以在这里做你想做的。但是,是的,你必须构建一个完整的面具。 这行得通,但是,虽然不是原始问题,但我需要一个最终矩阵,其中只有带有 NaN 的列,而不是参考号。尝试了单行但收到错误消息“未定义的函数或变量“a”。但我可能做错了什么。 @user3560490 我更正了单行,这必须是“A”而不是“a”。如果您只想要带有数字的矩阵,这要简单得多,其他答案也可以,很抱歉误解了它:) 这很棒。我想我了解 circshift 是如何工作的,但没有得到 bsxfun 所以只会接受整行。【参考方案4】:这是一个有趣的解决方案,我希望它表现得相当好,但请注意它有点棘手!
data(~data(:,2:end))=NaN
【讨论】:
有趣的解决方案......但如果您在任何奇数列中有 0,则会失败:您将在掩码列中写入 nan。 @Bentoy13 如前所述,这有点棘手。但是,由于问题提到了 3 位数字,这应该没问题。 哎呀,你完全正确!我忘记了这个限制,所以我搜索得太远了......恭喜! 精彩的一行!没有提到实际上只需要带有 NaN 的数据列,而不是参考列。【参考方案5】:使用逻辑索引:
even = a1(:,2:2:end); % even columns
odd = a1(:,1:2:end); % odd columns
odd(even == 0) = NaN; % set odd columns to NaN if corresponding col is 0
a1(:,1:2:end) = odd; % assign back to a1
a1 =
155 1 NaN 0
328 1 288 1
NaN 0 NaN 0
326 1 332 1
NaN 0 186 1
【讨论】:
欢迎来到 Stack Overflow!很高兴看到您想做出贡献,但请确保除了阅读问题之外,您还检查现有答案。在这种情况下,@Raab70 的现有答案实际上是相同的,因此通常不鼓励发布它。只要环顾四周,我相信您会找到足够多的问题来帮助提问者! 我的错,我发帖后才注意到这一点。 实际上,我对编写代码非常陌生,因此使用 cmets 将其设置得如此清晰非常有帮助。谢谢。以上是关于用 NaN 替换选择性数字的主要内容,如果未能解决你的问题,请参考以下文章