【问题标题】:Maximum values for two columns, need to use loops?两列的最大值,需要使用循环吗?
【发布时间】:2021-10-18 16:22:36
【问题描述】:

我一直在尝试使用循环,但它们只是不起作用,因为我之前没有做过任何处理这种复杂性的事情,我一直在尝试用 dplyer 来解决这个问题,这是一个不可能的练习。我不知道该怎么办。任何人都可以提出任何解决方案吗?

  • 有列 A_1 A_2 B_1 B_2 C_1 C_2 D_1 D_2 E_1 E_2 F_1 F_2 G_1 G_2...
  • 每行 1000 行
dat <- read.table(text = "ID    A_1   A_2    B_1   B_2    C_1   C_2    D_1   D_2    E_1   E_2    F_1   F_2    G_1   G_2
 11      1       2       3       4       3       4       3       4       3       4       3       4       3       4
 32      5       6       7       8       6       7       6       7       6       7       6       7       6       7
 73      15       15       10       10       3       4        3       4        3       4        3       4       2       2
 84      13       13       15       15       4       4        3       4        3       4        3       4       2       2
 65      2       2       2       2      2       2       2       2      2       2       2       1      2       2
                  ", header = TRUE)
  • 比较两列 A_1 和 A_2
  • 取最大值(例如 A_2)
  • 打印第三列中的最大值(selected_A_2 val)
  • 在第四列中打印最大的名称(selected_A_2 名称)
  • 基于 A_2 是最大的事实,取所有值 B_2、C_2、D_2、E_2...(分配新列 selected_B_2 名称、selected_B_2 val、selected_C_2 名称、selected_C_2 val)

使用 dplyer 调节上述内容非常简单。但是,以下是不可能的。

  • 但是,如果 A_1 == A_2,则比较 B_1 和 B_2
  • 取最大值(例如 B_1)
  • 打印第三列中的最大值(selected_B_1 val)
  • 在第四列中打印最大的名称(selected_B_1 名称)
  • 基于 B_1 是最大的事实,取所有值 B_1、C_1、D_1、E_1...(分配新列 selected_C_1 名称、selected_C_1 val、selected_D_1 名称、selected_D_1 val)

然后

  • 但是,如果 A_1 == A_2 和 B_1 == B_2 则比较 C_1 和 C_2 等等……
  • 如果碰巧所有人都是平等的,那么只需选择 A_1 B_1 C_1... 并继续前进

任何指导将不胜感激!

编辑:预期输出

黄色为终端比较,行的其余部分是否选择_1或_2列基于黄色项为_1或_2

【问题讨论】:

标签: r


【解决方案1】:

您是否考虑过在tidyverse 中使用case_when()?它允许复杂的向量化条件语句。例如,虽然我们没有您预期的输出,但此代码结构可以帮助您实现一些目标。

> dat <- dat %>% mutate(test = case_when(
+     A_1 == A_2 ~ case_when( #If A_1 and A_2 are the same, then check...
+         B_1 == B_2 ~ "wow",  #Whether B_1 and B_2 are the same and do "wow"
+         B_1 != B_2 ~ "cool"  #Whether they are different, and do "cool"
+     ),
+     A_1 != A_2 ~ "diff" #If the A's are not the same, define "diff"
+ ))

要了解这里发生了什么,第一个case_when() 正在检查 A_1 是否与 A_2 相同(对于每一行,它都将其作为向量进行)。如果是,则移动到下一个case_when() 并检查 B_1 是否等于 B_2,或者它们是否不同。你可以在这里看到输出。我根据这些嵌套的、可向量化的条件定义了一个新列test,从而不再需要 for 循环。

  ID A_1 A_2 B_1 B_2 C_1 C_2 D_1 D_2 E_1 E_2 F_1 F_2 G_1 G_2  test
1 11   1   2   3   4   3   4   3   4   3   4   3   4   3   4  diff
2 32   5   6   7   8   6   7   6   7   6   7   6   7   6   7  diff
3 73  15  15  10  10   3   4   3   4   3   4   3   4   2   2   wow
4 84  13  13  15  15   4   4   3   4   3   4   3   4   2   2   wow
5 65   2   2   2   2   2   2   2   2   2   2   2   1   2   2   wow

对于您希望做但一直在努力做的事情下的第三个和第四个要点,您可以使用mutate() 函数轻松完成这些嵌套结构,以根据需要定义这些新列,就像我所做的那样。

也就是说,对于 C、D 等的进一步迭代,您必须在这里开发相当嵌套的条件。可能有一种更优雅的方法来解决这个问题,但这种方法通常应该有效。您可以进一步添加更多层case_when()。所以,在我的示例代码中,从第 3 行开始,它可能看起来像

B_1 == B_2 ~ case_when(
     C_1 == C_2 ~ case_when(
         ....
     ),
B_1 > B_2 ~ B_1, #New col's rows meeting this condition are assigned B_1
B_2 > B_1 ~ B_2 #These last two are my attempt to do your 3rd bullet point

不过,我不确定您所说的“最大名称”是什么意思——您的列是否同时包含字符数据和当前作为字符保存的数字?

【讨论】:

  • 最大名称是指从中选择最大值的列的名称(因此,如果 A_1=8,A_2=13)最大值为 13,列的名称为 A_2 (我当时在想这将允许我设置条件以便选择 B_2、C_2 等)。
  • @mgtrek 嗯,我明白了。我认为,如果您创建的示例输出至少包含 A、B、C 和 D 列,我可以想出一个精确的解决方案。
  • 谢谢,我用 A/B/C/D 列手动创建了一个输出,如果有什么不明白的地方请告诉我。同时阅读有关 case_when 的使用! (碰巧他们都变成了_2……)
猜你喜欢
  • 2020-11-18
  • 2015-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-24
  • 2012-08-26
  • 2016-10-06
  • 2018-09-21
相关资源
最近更新 更多