【问题标题】:Getting rowSums for triplicate records and retaining only the one with highest value获取一式三份记录的 rowSums 并仅保留具有最高值的记录
【发布时间】:2019-06-28 02:34:32
【问题描述】:

我有一个包含 163 个观察值和 65 列的数据框,其中包含一些动物数据。 163 次观察来自 56 只动物,每一种都应该有三次重复的记录,但一些信息丢失了,所以对于大多数动物来说,我有三次重复(“A”、“B”、“C”),而对于一些我有仅重复(在“A”和“B”、“A”和“C”以及“B”和“C”之间变化)。

第 13:65 列包含一些我想总结的信息,并且只保留 rowSums 值较高的一式三份。所以我的数据框会是这样的:

  ID    Trip     Acet    Cell   Fibe   Mega   Tera
1   4      A        2       4      9      8      3  
2   4      B        9       3      7      5      5  
3   4      C        1       2      4      8      6 
4   12     A        4       6      7      2      3 
5   12     B        6       8      1      1      2 
6   12     C        5       5      7      3      3 

我不确定我需要的是编写自己的函数还是循环,或者实际上最好的替代方法是什么 - 抱歉,我仍在学习,不幸的是,对我来说,我不像程序员那样思考让事情变得更具挑战性...

所以我想知道的是保留第 2 行和第 6 行(在每只动物的三次重复中,它们的 rowSums 最高),但对于整个数据框。结果我想要的是

    ID    Trip    Acet    Cell   Fibe   Mega   Tera
1   4      B       9       3      7      5      5  
2   12     C       5       5      7      3      3

如果问题没有详细阐述或没有意义,我真的很抱歉,这是我第一次在这里提问,我最近才开始学习 R。

【问题讨论】:

  • 我认为由于您的示例同时包含数字和字符值,因此它不是矩阵,而是数据框。
  • 是的,您完全正确,对此感到抱歉!我也更正了文字。谢谢!

标签: r function dataframe rowsum


【解决方案1】:

我们可以单独创建行总和,并使用ave 来查找具有最大行总和的行。然后使用逻辑向量对数据集的行进行子集化

nm1 <- startsWith(names(df1), "V")

OP 更新了列名。在这种情况下,无论是索引

nm1 <- 3:7

或者选择带有setdiff的列

nm1 <- setdiff(names(df1), c("ID", "Trip"))

v1 <- rowSums(df1[nm1], na.rm = TRUE)
i1 <- with(df1, v1 == ave(v1, ID, FUN = max))
df1[i1,]
#  ID Trip V1 V2 V3 V4 V5
#2  4    B  9  3  7  5  5
#6 12    C  5  5  7  3  3

数据

df1 <- structure(list(ID = c(4L, 4L, 4L, 12L, 12L, 12L), Trip = structure(c(1L, 
2L, 3L, 1L, 2L, 3L), .Label = c("A", "B", "C"), class = "factor"), 
    V1 = c(2L, 9L, 1L, 4L, 6L, 5L), V2 = c(4L, 3L, 2L, 6L, 8L, 
    5L), V3 = c(9L, 7L, 4L, 7L, 1L, 7L), V4 = c(8L, 5L, 8L, 2L, 
    1L, 3L), V5 = c(3L, 5L, 6L, 3L, 2L, 3L)), 
    class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6"))

【讨论】:

  • 好吧,对不起,这真的是我的错,列实际上有名字,我只是用通用的“V”作为例子。我已经在示例中纠正了这一点。我可以用什么代替nm1 &lt;- startsWith(names(df1), "V") # I would need to identify the columns by position, as their names are long and all different
  • @czarniutki 然后,如果您知道列索引,则可以使用索引,v1 &lt;- rowSums(df1[3:7], na.rm = TRUE)
  • 我成功了!!非常非常感谢您的贡献和耐心!
  • 是的,我花了一段时间,但我设法弄清楚了 - 抱歉,仍在学习,但非常感谢您的帮助!
  • @czarniutki 很高兴你能弄明白。我离开了
【解决方案2】:

这是一种方法。

library(tidyverse)

dat2 <- dat %>%
  mutate(Sum = rowSums(select(dat, starts_with("V")))) %>%
  group_by(ID) %>%
  filter(Sum == max(Sum)) %>%
  select(-Sum) %>%
  ungroup()
dat2
# # A tibble: 2 x 7
#      ID Trip     V1    V2    V3    V4    V5
#   <int> <fct> <int> <int> <int> <int> <int>
# 1     4 B         9     3     7     5     5
# 2    12 C         5     5     7     3     3

这是另一个。即使有多行且行总和等于最大值,此方法也可确保仅保留一行。

dat3 <- dat %>%
  mutate(Sum = rowSums(select(dat, starts_with("V")))) %>%
  arrange(ID, desc(Sum)) %>%
  group_by(ID) %>%
  slice(1) %>%
  select(-Sum) %>%
  ungroup()
dat3
# # A tibble: 2 x 7
#      ID Trip     V1    V2    V3    V4    V5
#   <int> <fct> <int> <int> <int> <int> <int>
# 1     4 B         9     3     7     5     5
# 2    12 C         5     5     7     3     3

数据

dat <- read.table(text = "  ID    Trip     V1     V2    V3    V4    V5
1   4      A       2      4     9     8     3  
2   4      B       9      3     7     5     5  
3   4      C       1      2     4     8     6 
4   12     A       4      6     7     2     3 
5   12     B       6      8     1     1     2 
6   12     C       5      5     7     3     3 ",
                  header = TRUE)

【讨论】:

  • 好吧,对不起,这真的是我的错,列实际上有名字,我只是用通用的“V”作为例子。我已经在示例中纠正了这一点。我可以用什么代替nm1 &lt;- startsWith(names(df1), "V") # I would need to identify the columns by position, as their names are long and all different
  • 好的,我用过mutate(Sum = rowSums(select(dat, range(5:65)))),效果很好。非常非常感谢!!!
猜你喜欢
  • 2021-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-20
相关资源
最近更新 更多