【问题标题】:How to create a new matrix from output of another matrix using loops and functions?如何使用循环和函数从另一个矩阵的输出创建一个新矩阵?
【发布时间】:2021-11-30 23:59:51
【问题描述】:

如何创建一个函数 points (),它以矩阵 goals 作为输入,有 2 列,其中行数取决于用户的输入?第一栏是主场进球,第二栏是客场进球。我怎样才能得到目标矩阵,该函数需要第二个输入 win_points,该输入指定了球队获得的积分数?

例如,赢3分,平分1分,输0分。因此,如果球队以 1-0 获胜,则 win_point 矩阵应显示为 3 0,如果球队以 4-4 获胜,则 win_point 矩阵应显示为 1 1 以分为单位。

我也这样尝试过,但我认为使用 function 效果会更好。 我现在在我的代码中使用了一个 10 行和 2 列的矩阵,行应该是灵活的(你可以放置每个数量的行)并且列应该是 2 个固定的,因为一场比赛只有 2 个团队。

我在下面的代码中做错了什么?

set.seed(1)
goals1 <- matrix(sample(0:5, size = 5*2, replace = TRUE), nrow=5, ncol=2)
points1 <- matrix(0, nrow(goals1),ncol(goals1))
for(i in 1:nrow(goals1)) {
  for(j in 1:ncol(goals1)) {
    if goals1[goals1[i]>goals1[j]] {
      points1[i] <- 3
      points1[j] <- 0
    } else if goals1[goals1[i]<goals1[j]] {
      points1[i] <- 0
      points1[j] <- 3
    } else if goals1[goals1[i]==goals1[j]] {
      points1[i] <- 1
      points1[j] <- 1
    }
  }
}

首先,感谢您提供正确代码的答案!但是为什么上面的代码不起作用?我不明白我在代码中做错了什么。谁能解释一下!

【问题讨论】:

    标签: r function loops if-statement matrix


    【解决方案1】:

    您可以创建一个简单的矢量化函数,该函数将分数矩阵、获胜的点数(默认为 3)和平局的点数(默认为 1)作为参数。然后,我们可以使用胜负分作为乘数,对每场比赛的得分进行逻辑比较。这里不需要循环。

    points <- function(goals, win_points = 3, draw_points = 1)
    {
      
      data.frame(home = win_points * as.numeric(goals[,1] > goals[,2]) + 
                        draw_points * (goals[,1] == goals[,2]),
                 away = win_points * as.numeric(goals[,2] > goals[,1]) + 
                        draw_points * (goals[,2] == goals[,1])) |>
        as.matrix()
    }
    

    因此,创建一个随机目标矩阵,我们得到:

    set.seed(1)
    
    goals <- matrix(sample(0:5, size = 10*2, replace = TRUE), nrow=10, ncol=2)
    colnames(goals) <- c("Home", "Away")
    
    goals
    #>       Home Away
    #>  [1,]    0    0
    #>  [2,]    3    4
    #>  [3,]    0    4
    #>  [4,]    1    1
    #>  [5,]    4    5
    #>  [6,]    2    5
    #>  [7,]    5    1
    #>  [8,]    1    0
    #>  [9,]    2    4
    #> [10,]    2    4
    

    我们可以很容易地从目标矩阵中得到点矩阵:

    points(goals)
    #>       home away
    #>  [1,]    1    1
    #>  [2,]    0    3
    #>  [3,]    0    3
    #>  [4,]    1    1
    #>  [5,]    0    3
    #>  [6,]    0    3
    #>  [7,]    3    0
    #>  [8,]    3    0
    #>  [9,]    0    3
    #> [10,]    0    3
    

    编辑

    如果出于某种原因您想要一个循环,则需要简化逻辑并只使用一个循环 - 因为只有两列,您不需要遍历列,只需比较第 1 列和第 2 列在每一行。以下是一个工作示例:

    for(i in 1:nrow(goals1)) {
        if(goals1[i, 1] > goals1[i, 2]) {
          points1[i, 1] <- 3
          points1[i, 2] <- 0
        } else if (goals1[i, 1] < goals1[i, 2]) {
          points1[i, 1] <- 0
          points1[i, 2] <- 3
        } else if (goals1[i, 1] == goals1[i, 2]) {
          points1[i, 1] <- 1
          points1[i, 2] <- 1
        }
    }
    

    reprex package (v2.0.0) 于 2021-10-12 创建

    【讨论】:

    • 我想我很清楚你做了什么,非常感谢!我想知道是否可以在 1 步中为 winpoints 创建一个矩阵,而不是先将其作为数据框?
    • @Wutruvic 您可以将两个向量 cbind 放在一起,而不是将它们作为数据框,但是您还需要给出列名。您也可以将数据框包装在 as.matrix 中,而不是使用管道运算符。为什么这很重要?
    • 我想知道如果您避免使用循环而不是使用逻辑索引,您是否可以获得相同的结果?是不是也能得到这个结果?
    • 我稍微编辑了我的问题,你能解释一下我在 if 和 if else 语句中做错了什么吗?我在我的代码中找不到我做错了什么,但我很想修复它。
    • @Wutruvic 您自己的代码存在一些问题。你的 if 语句没有用括号括起来,所以这段代码甚至不能在 R 中运行。其次,不清楚你在用你的循环做什么。例如,在内部循环的第一次迭代中,您正在检查goals1[goals1[i]&gt;goals1[j]],但由于ij 都是1,这简化为goals1[FALSE],这没有任何意义。请记住,您需要使用两个索引来指定您所指的行和列:例如goal1[i, j]。但是这个逻辑对你当前的代码没有意义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-04
    • 2021-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-27
    • 1970-01-01
    相关资源
    最近更新 更多