【问题标题】:Remove duplicate rows based on content of three different columns根据三个不同列的内容删除重复行
【发布时间】:2020-03-12 16:18:40
【问题描述】:

我想根据其他三列的内容从我的数据框中删除重复的行。

   name   col1  col2  col3
1  BOB    HIGH  NO    1
2  BOB    MID   NO    1
3  BILL   MID   YES   2
4  BILL   MID   NO    3
5  KAREN  LOW   YES   7.5
6  KAREN  LOW   YES   10
7  STEVE  LOW   NO    1
8  STEVE  LOW   NO    1
9  PETE   LOW   NO    -4
10 PETE   LOW   NO    -5 

从这里我想首先在 col1 上选择“HIGH”>“MID”>“LOW”。如果两者相同,请选择 col2 并选择“YES”>“NO”。如果两者相同,则选择 col3,其中 +∞ > -∞。如果三者相同,则保留两者。

所以在这个例子中是:

   name   col1  col2  col3
1  BOB    HIGH  NO    1
3  BILL   MID   YES   2
6  KAREN  LOW   YES   10
7  STEVE  LOW   NO    1
8  STEVE  LOW   NO    1
9  PETE   LOW   NO    -4

R 和 python 解决方案都可以接受。

编辑:阐明 col3 的条件。

编辑2: 这为我解决了。感谢@Adam 的帮助!

df %>%
  group_by(name) %>% 
  mutate(col1 = factor(col1, levels = c("LOW", "MID", "HIGH")),
         col2 = factor(col2, levels = c("NO", "YES")),
         interact = as.character(interaction(c(col1), c(col2))),
         rank = dense_rank(desc(interact))) %>% 
  filter(rank == min(rank)) %>%
  filter(col3 == max(col3)) %>%
  select(-c(interact, rank))

【问题讨论】:

  • 看起来像一个简单的 'arrange()' 然后 'x[!duplicated(x)]'

标签: r python-3.x


【解决方案1】:

数据:

df <- read.table(textConnection("name   col1  col2  col3
1 BOB    HIGH  NO    1
2 BOB    MID   NO    1
3 BILL   MID   YES   2
4 BILL   MID   NO    3
5 KAREN  LOW   YES   1
6 KAREN  LOW   YES   2
7 STEVE  LOW   NO    1
8 STEVE  LOW   NO    1"), header = TRUE)

解决方案:

按顺序设置因子级别将允许按照您的定义进行排序。这些可以与interaction() 混合在一起。我现在转成字符,这样排名就如我们预期的那样。

我使用dense_rank() 而不是一些删除重复的方法,以便我们可以按照您的描述保持联系。

编辑:为col3 添加了填充,以便字符排序正常工作。我再次将其作为可以删除的额外虚拟列保留。

library(dplyr)
library(stringr)

df %>%
  group_by(name) %>% 
  mutate(col1 = factor(col1, levels = c("LOW", "MID", "HIGH")),
         col2 = factor(col2, levels = c("NO", "YES")),
         col3_pad = str_pad(col3, width = max(str_length(col3)), pad = 0),
         interact = as.character(interaction(c(col1), c(col2), col3_pad)),
         rank = dense_rank(desc(interact))) %>% 
  filter(rank == min(rank))

结果:

我留下了虚拟列以显示发生了什么。但是你现在可以放下它们了。

# A tibble: 5 x 6
# Groups:   name [4]
  name  col1  col2   col3 interact  rank
  <fct> <fct> <fct> <int> <chr>    <int>
1 BOB   HIGH  NO        1 3.1.1        1
2 BILL  MID   YES       2 2.2.2        1
3 KAREN LOW   YES       2 1.2.2        1
4 STEVE LOW   NO        1 1.1.1        1
5 STEVE LOW   NO        1 1.1.1        1

【讨论】:

  • 今天注意到,当 col3 > 9 时,交互不起作用,但会选择具有最大第一个整数的那个。例如。如果我将 KAREN 更改为 9 和 10,此代码将选择 9 而不是 10。
  • 啊,基于文本排序,这很有意义。这可以通过填充到最大宽度来解决。例如,如果您最大的 col3 是 4 位数字,则添加前导零以使所有数字都变宽。我正在更新。
  • col3 上的 +some binning 解决了这个问题,非常感谢!作为一个学习/兴趣问题,我注意到这段代码不能很好地处理十进制数或负数。例如。 -5 被选中超过 -4 和 7.5 被选中超过 10。我没有解决它以防万一有人有同样的问题,因为原始问题尚未得到回答。 “ +∞ > -∞ ”部分仍然存在。
猜你喜欢
  • 2017-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-10
  • 2017-07-06
  • 2019-05-29
  • 1970-01-01
相关资源
最近更新 更多