用 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 替换选择性数字的主要内容,如果未能解决你的问题,请参考以下文章

用一系列非数字对象中最接近的值替换 NaN?

用一系列非数字对象中最接近的值替换 NaN?

如何用熊猫(python)中的其他值替换NAN [重复]

IND和NAN号有啥区别

Wps文字替换功能,怎么替换指定字母后面的回车符,例如只替换选择题ABCD四行后面的回车符为制表符

Julia:用数组中的字符串替换数字