首页 > 解决方案 > 如何根据这些列子集的排序来改变 R 中的列?

问题描述

首先,假设我们有一个这样的数据集:

data <- data.frame(
  id = 1:5,
  time = c(0.1, 0.2, 0.1, 0.1, 0.2),
  obj_a_size = c(1, 3, 8, 4, 2),
  obj_a_cuteness = c(3, 6, 4, 1, 2),
  obj_b_size = c(5, 4, 4, 2, 5),
  obj_b_cuteness = c(6, 2, 10, 9, 6),
  obj_c_size = c(3, 6, 7, 1, 6),
  obj_c_cuteness = c(10, 1, 6, 8, 8)
)

它有关于整个实验的列(如time)和特定于对象的列(如X_sizeX_cuteness)。不过,这些对象是随机排序的,所以我想改变这些列,以分别为每个实验按大小排序对象。我期望的结果是这样的:

data <- data.frame(
  id = 1:5,
  time = c(0.1, 0.2, 0.1, 0.1, 0.2),
  obj_max_size = c(5, 6, 8, 4, 6),
  obj_max_cuteness = c(6, 1, 4, 1, 8),
  obj_2nd_size = c(3, 4, 7, 2, 5),
  obj_2nd_cuteness = c(10, 2, 6, 9, 6),
  obj_min_size = c(1, 3, 3, 1, 2),
  obj_min_cuteness = c(3, 6, 10, 8, 2)
)

请注意,可爱度不是按降序或升序排列的,但我希望将可爱度视为对象的一部分并设置obj_max_cuteness = obj_2_cuteness在任何地方obj_max_size = obj_2_size,依此类推。

预先知道对象的数量(其中有四个),列也是已知的,并且有四个列描述每个对象。没有丢失的数据。如有必要,我愿意使用任何软件包。此外,原始数据集约为 500k x 30,因此快速或内存友好代码的奖励积分。

编辑:有些人注意到描述不是很清楚。我所追求的是一点面向对象的东西:在上面的例子中,实验中的每个对象都可以这样描述(X意味着obj_X_它属于实验号X):

obj_1_a = {"size": 1, "cuteness": 3}
obj_1_b = {"size": 5, "cuteness": 6}
obj_1_c = {"size": 3, "cuteness": 10}
obj_2_a = {"size": 3, "cuteness": 6}
...

我想按大小重新排序它们,以便(在结果数据框中):

obj_1_max = {"size": 5, "cuteness": 6}
obj_1_2nd = {"size": 3, "cuteness": 10}
obj_1_min = {"size": 1, "cuteness": 3}
obj_2_max = {"size": 6, "cuteness": 1}
...

标签: rdplyr

解决方案


这就是你所追求的吗?最小值和最大值计算很简单。要找到第二个最大值,您需要做更多的工作。我对第二个值的解释是它是排序和唯一值的第二个值。我的输出与您的不同,但这可能是由于您对第二个值的含义的不同解释。我的阅读:您正在寻找从最大值下降的第一个值;来自 3 列(大小、可爱度)的组。

library(dplyr)

data <- data.frame(
      id = 1:5,
      time = c(0.1, 0.2, 0.1, 0.1, 0.2),
      obj_a_size = c(1, 3, 8, 4, 2),
      obj_a_cuteness = c(3, 6, 4, 1, 2),
      obj_b_size = c(5, 4, 4, 2, 5),
      obj_b_cuteness = c(6, 2, 10, 9, 6),
      obj_c_size = c(3, 6, 7, 1, 6),
      obj_c_cuteness = c(10, 1, 6, 8, 8)
    )

obj_max_size <- data %>%
  pivot_longer(cols = contains('size')) %>%
  group_by(id) %>%
  summarise(obj_max_size = max(value)) %>%
  ungroup() %>%
  select(obj_max_size)

obj_min_size <- data %>%
  pivot_longer(cols = contains('size')) %>%
  group_by(id) %>%
  summarise(obj_min_size = min(value)) %>%
  ungroup() %>%
  select(obj_min_size)

obj_2nd_size <- data %>%
  pivot_longer(cols = contains('size')) %>%
  group_by(id) %>%
  distinct(value) %>%
  arrange(desc(value)) %>%
  slice(2) %>%
  ungroup() %>%
  select(obj_2nd_size = value)

obj_max_cuteness <- data %>%
  pivot_longer(cols = contains('cuteness')) %>%
  group_by(id) %>%
  summarise(obj_max_cuteness = max(value)) %>%
  ungroup() %>%
  select(obj_max_cuteness)

obj_min_cuteness <- data %>%
  pivot_longer(cols = contains('cuteness')) %>%
  group_by(id) %>%
  summarise(obj_min_cuteness = min(value)) %>%
  ungroup() %>%
  select(obj_min_cuteness)

obj_2nd_cuteness <- data %>%
  pivot_longer(cols = contains('cuteness')) %>%
  group_by(id) %>%
  distinct(value) %>%
  arrange(desc(value)) %>%
  slice(2) %>%
  ungroup() %>%
  select(obj_2nd_cuteness = value)


output <- bind_cols(id = data$id, obj_max_size, obj_min_size, obj_2nd_size, obj_max_cuteness, obj_min_cuteness, obj_2nd_cuteness)

看起来output像这样:

> output
# A tibble: 5 x 7
     id obj_max_size obj_min_size obj_2nd_size obj_max_cuteness obj_min_cuteness obj_2nd_cuteness
  <int>        <dbl>        <dbl>        <dbl>            <dbl>            <dbl>            <dbl>
1     1            5            1            3               10                3                6
2     2            6            3            4                6                1                2
3     3            8            4            7               10                4                6
4     4            4            1            2                9                1                8
5     5            6            2            5                8                2                6

推荐阅读