【问题标题】:Remove rows of matrix on multiple conditions在多个条件下删除矩阵行
【发布时间】:2019-12-13 13:03:43
【问题描述】:

这个问题最好通过例子来解决。

设置

Mat1 <- matrix(nrow =9, ncol =11)
colnames(Mat1) <- c("Name", "Strategy.Assets", "Jan.94", "Jan.95", "Jan.96", "Jan.97", "1", "2", "3","4", "5")
Mat1[,1] <- letters[1:9]
Mat1[,2] <- cbind(20,30,40,50,60,30,30,40,50)
Mat1[,3:6] <- rnorm(36,0,1)
Mat1[,7] <- c(0,0,0,0,0,0,0,0,0)
Mat1[,8] <- c(0.95, 0.8, 0,0,0,0,0,0,0)
Mat1[,9] <- c(0.95,0.6,0.7,0,0,0,0,0,0)
Mat1[,10] <- c(0.08, 0.09, 0.99, 0.93, 0,0,0,0,0)
Mat1[,11] <- c(0.09,0.01,0.04,0.97, 0.80,0,0,0,0)

data.frame(Mat1)

将列“1”“2”“3”“4”“5”“6”视为相关矩阵的开头(它应该是 9 x 9,但我只显示前 6 列)。

对于第 1 到第 6 列中的每一行,我需要确定是否有一个值 >= 0.95。如果有,我需要知道位置。在这种情况下,值 0.95 出现在相关矩阵的条目 m=1,n=2 中。然后,我需要转到“策略资产”列并比较第 1 行和第 2 行中的值(在本例中为 20 和 30)。在此之后,我需要省略值较低的行(第 1 行,因为 20 小于 30)。删除一行后,我需要继续到相关矩阵中的下一行 - 我们看到在第 2 行中,没有至少等于 0.95 的值。然后我们进入第三排。然后我们看到 0.99 >0.95 出现在位置 m=3,n=4。然后我们转到“策略资产”并比较第 3 行和第 4 行中的值。在第 3 行中,策略资产 = 40,第 4 行 = 50。因此我们省略了第 3 行。然后我们继续进行相关矩阵的第 4 行。在位置 4,5 0.99 发生。然后,我们需要比较策略资产中的第 4 行和第 5 行。我们看到第 5 行 =60,第 4 行=50,所以需要省略第 4 行。

我需要对相关矩阵中的所有行重复此过程。

请注意,相关矩阵的条目 (1,3) 也等于 0.95。但是,由于 row1 已经被删除(从第一次迭代中),在这种情况下我不需要循环继续运行。

  > data.frame(Mat1)
  Name Strategy.Assets             Jan.94             Jan.95             Jan.96              Jan.97 X1   X2   X3   X4   X5
1    a              20   2.95438832384095  0.322838398649362  0.265489849080971   -1.26762589628627  0 0.95 0.95 0.08 0.09
2    b              30 -0.231467724347497   1.36209337396348  0.244352997300369   0.147019042483708  0  0.8  0.6 0.09 0.01
3    c              40 -0.725388339795491 0.0813983643917171  -0.50418751522557   0.802967414744253  0    0  0.7 0.99 0.04
4    d              50 -0.120645568994363    1.7770242881308 -0.798437656907533    1.03842921924565  0    0    0 0.93 0.97
5    e              60  0.818447801042692 -0.767858384307916  -1.23187047713004 -0.0779863946287645  0    0    0    0  0.8
6    f              30 -0.231572883434978  0.266559660007751  0.720829574412722 -0.0207732265889516  0    0    0    0    0
7    g              30  0.444651868913969  0.832322051653509 -0.538333881677844   0.291130047037627  0    0    0    0    0
8    h              40   2.00827324376109  0.775006479679076 0.0323592399331455   -2.33121256833447  0    0    0    0    0
9    i              50 -0.368493048065977   1.30727697822673 -0.446402751994181 -0.0616057412430855  0    0    0    0    0

那么我想要的输出是:

output <- data.frame(rbind(Mat1[2,1:6], Mat1[5:9,1:6]))
output

  Name Strategy.Assets             Jan.94             Jan.95             Jan.96              Jan.97
1    b              30 -0.231467724347497   1.36209337396348  0.244352997300369   0.147019042483708
2    e              60  0.818447801042692 -0.767858384307916  -1.23187047713004 -0.0779863946287645
3    f              30 -0.231572883434978  0.266559660007751  0.720829574412722 -0.0207732265889516
4    g              30  0.444651868913969  0.832322051653509 -0.538333881677844   0.291130047037627
5    h              40   2.00827324376109  0.775006479679076 0.0323592399331455   -2.33121256833447
6    i              50 -0.368493048065977   1.30727697822673 -0.446402751994181 -0.0616057412430855

我需要能够将此函数应用于列表中的矩阵。列表中的每个矩阵都有不同的行数,因此也有不同的列数。但是前 6 列始终相同。本质上,“名称”变量增加(可能是从 a 到 z),导致相关矩阵增加。(在这种情况下为 26 x 26)。

【问题讨论】:

  • 当您将数据保存在矩阵中时,由于Name 列,其中的所有值都将转换为字符。您要将其保留为矩阵还是将其转换为数据框?同样在此示例中仅删除了一行,您可以添加一个更详细的示例,删除多行以便更容易理解。
  • 为什么要使用矩阵?查看各种类型的变量,在我看来data.framedata.tabletibble 更合适...
  • 一秒钟。我将它作为一个 data.frame 框架并扩展示例。我现在还在学习 R。
  • "然后我需要转到“战略资产”列并比较 1 和 2 的值(在本例中为 20 和 30)。“我没有非常关注你:strategy.assets 的 1 和 2 的值是什么?列 12 没有 20 和 30,如果我过滤 2 >= 0.95 的数据,我只会得到 strategy.assets 等于 20
  • @PavoDive 已编辑。它的意思是在“战略资产”列的“第 1 行和第 2 行”中阅读

标签: r for-loop if-statement conditional-statements subset


【解决方案1】:

如果我对您的理解正确,一种方法可能是首先使用which 找出相关列的值大于等于 0.95 的行和列索引。对于每一对行和列,我们找出对应的最小值并从原始Mat1 中删除该行。

mat <- which(Mat1[, as.character(1:5)] >= 0.95, arr.ind = TRUE)
Mat1[-unique(apply(mat, 1, function(x) x[which.min(Mat1$Strategy.Assets[x])])), ]


#  Name Strategy.Assets      Jan.94      Jan.95     Jan.96     Jan.97 1   2   3    4    5
#2    b              30 -0.02101158  1.27504998 -0.9534582 -0.6917499 0 0.8 0.6 0.09 0.01
#5    e              60 -0.88500700 -1.19165574 -1.6309657  0.6183648 0 0.0 0.0 0.00 0.80
#6    f              30 -0.45072999 -0.04698659  0.7462178  0.5858741 0 0.0 0.0 0.00 0.00
#7    g              30  1.29131284 -1.60004027 -0.9681269  0.9595044 0 0.0 0.0 0.00 0.00
#8    h              40  0.37883959 -1.11536574 -0.3041997 -0.8202406 0 0.0 0.0 0.00 0.00
#9    i              50  1.50068308  0.89465888  0.6646096  0.4433313 0 0.0 0.0 0.00 0.00

数据

Mat1 <- data.frame(matrix(nrow =9, ncol =11))
colnames(Mat1) <- c("Name", "Strategy.Assets", "Jan.94", "Jan.95", "Jan.96", 
                 "Jan.97", "1", "2", "3","4", "5")

Mat1[,1] <- letters[1:9]
Mat1[,2] <- c(20,30,40,50,60,30,30,40,50)
Mat1[,3:6] <- rnorm(36,0,1)
Mat1[,7] <- c(0,0,0,0,0,0,0,0,0)
Mat1[,8] <- c(0.95, 0.8, 0,0,0,0,0,0,0)
Mat1[,9] <- c(0.95,0.6,0.7,0,0,0,0,0,0)
Mat1[,10] <- c(0.08, 0.09, 0.99, 0.93, 0,0,0,0,0)
Mat1[,11] <- c(0.09,0.01,0.04,0.97, 0.80,0,0,0,0)

【讨论】:

  • 这家伙太棒了!非常感谢。我稍后会将此标记为答案(其他人可能有其他想法)。但我现在可以用这个!谢谢老哥
猜你喜欢
  • 2022-01-26
  • 1970-01-01
  • 1970-01-01
  • 2018-10-04
  • 1970-01-01
  • 2016-12-21
  • 1970-01-01
  • 1970-01-01
  • 2019-04-07
相关资源
最近更新 更多