R中矩阵的条件和减法

时间:2018-11-08 21:15:48

标签: r

我看过R create a vector from conditional operation on matrix,并且使用类似的解决方案并不能达到我想要的效果(并且我不确定为什么)。

我的目标是在以下条件下评估dfif df > 2, df -2, else 0

df

a <- seq(1,5)
b <- seq(0,4)
df <- cbind(a,b) %>% as.data.frame()

df很简单:

a b
1 0
2 1
3 2
4 3
5 4

df_final在使用适当的功能后应如下所示:

a b
0 0
0 0
1 0
2 1
3 2

我在结果中应用了以下函数,但是我不确定为什么它不起作用(对解决方案的进一步解释将不胜枚举)

apply(df,2,function(df){
     ifelse(any(df>2),df-2,0)
 })

满足以下条件:

 a  b 
-1 -2

谢谢您的社区!

3 个答案:

答案 0 :(得分:2)

通过减去2创建'out'数据集,然后将基于逻辑条件的值替换为0

out <- df - 2
out[out < 0] <- 0

或一步一步

(df-2) * ((df - 2) > 0)

答案 1 :(得分:2)

让我们修复您的功能并了解为什么它不起作用:

apply(df,  # apply to df
       2,  # to each *column* of df 
       function(df){  # this function. Call the function argument (each column) df 
                      #  (confusing because this is the same name as the data frame...)
         ifelse(  # Looking at each column...
              any(df > 2),  # if there are any values > 2
              df - 2,       # then df - 2
              0             # otherwise 0
          )
 })

any()返回单个值。 ifelse()返回的形状与测试相同,因此通过使测试any(df > 2)(单个值),ifelse()也将返回单个值。

我们可以通过以下方法解决此问题:(a)将函数的名称更改为与输入不同的名称(出于可读性考虑),以及(b)取消any

apply(df,  # apply to df
       2,  # to each *column* of df 
       function(x){   # this function. Call the function argument (each column) x
         ifelse(  # Looking at each column...
              x > 2,  # when x is > 2
              df - 2, # make it x - 2
              0       # otherwise 0
          )
 })

apply用于处理矩阵。当给它一个数据帧时,它要做的第一件事就是将其转换为矩阵。如果要将结果作为数据帧,则需要将其转换回数据帧。

或者我们可以改用lapplylapply返回一个list,通过使用df将其分配到df[] <- lapply()的列中,我们不需要进行转换。 (并且由于lapply不进行矩阵转换,因此默认情况下它知道将函数应用于每一列。)

df[] <- lapply(df, function(x) ifelse(x > 2, x - 2, 0))

请注意,df <- cbind(a,b) %>% as.data.frame()是写df <- data.frame(a, b)的更复杂的方式

答案 2 :(得分:1)

使用申请

a <- seq(1,5)
b <- seq(0,4)
df <- cbind(a,b) %>% as.data.frame()

new_matrix <- apply(df, MARGIN=2,function(i)ifelse(i >2, i-2,0)) 
new_matrix
###if you want it to return a tibble/df
new_tibble <- apply(df, MARGIN=2,function(i)ifelse(i >2, i-2,0)) %>% as_tibble()