R unpivot列与排名组合

R unpivot columns with ranked combination

我有以下数据框,其 dput 样本是:

MyData <- structure(list(Tag = c("Tag1", "Tag1","Tag1", "Tag1","Tag1", "Tag1","Tag1", "Tag2","Tag2", "Tag2"), id = c(15227L, 16368L, 15121L, 15122L,15123L, 15124L, 15125L, 15391L, 15392L, 15393L), dimension_r = c(10,2, 3, 4, 5, 6, 7, 6, 7, 8)), row.names = c(1L, 2L, 3L, 4L,5L, 6L, 7L, 62L, 63L, 64L), class = "data.frame") 

看起来像这样:

Tag     ID      Rank
Tag1    15227   10
Tag1    16368   2
Tag1    15121   3
Tag1    15122   4
Tag1    15123   5
Tag1    15124   6
Tag1    15125   7
Tag2    15391   6
Tag2    15392   7
Tag2    15393   8

我想将其重新格式化为如下所示:

Tag     lower greater
Tag1    16368 15121     
Tag1    15121 15122     
Tag1    15122 15123 
Tag1    15123 15124
Tag1    15124 15125
Tag1    15125 15227 
Tag2    15391 15392
Tag2    15392 15393

我想我需要为此使用 dcast,但不确定如何对其进行编程才能获得排名并以这种方式反转框架。

在 base R 中,一种方法可能是首先 order 基于 Tagdimension_r 的数据。我们根据 Tag 拆分 newdata 并通过分别忽略最后和第一个观察来创建 lowergreater 列。

newdata <- MyData[with(MyData, order(Tag, dimension_r)), ]
output <- do.call(rbind, lapply(split(newdata, newdata$Tag), function(x) 
        data.frame(Tag = x$Tag[1L], lower = x$id[-nrow(x)], greater = x$id[-1])))
rownames(output) <- NULL

output
#   Tag lower greater
#1 Tag1 16368   15121
#2 Tag1 15121   15122
#3 Tag1 15122   15123
#4 Tag1 15123   15124
#5 Tag1 15124   15125
#6 Tag1 15125   15227
#7 Tag2 15391   15392
#8 Tag2 15392   15393

我们可以使用 dplyrpurrr::map_df

实现相同的逻辑
library(dplyr)
MyData %>%
  arrange(Tag, dimension_r) %>%
  group_split(Tag) %>%
  purrr::map_df(~data.frame(Tag = first(.$Tag), 
                lower = .$id[-nrow(.)], greater = .$id[-1]))

一种data.table方法

1 将数据转换为data.table,并按Tag by id进行汇总(创建lower)
2 使用data.table::shift通过Tag-group
得到下一个值 3 使用 na.omit 丢弃不完整的行。

library(data.table)
na.omit( setDT(MyData)[, .(lower = id ), by = .(Tag)][, greater := shift(lower, type = "lead"), by = .(Tag)][] )

   Tag lower greater
1: Tag1 15227   16368
2: Tag1 16368   15121
3: Tag1 15121   15122
4: Tag1 15122   15123
5: Tag1 15123   15124
6: Tag1 15124   15125
7: Tag2 15391   15392
8: Tag2 15392   15393

简单地使用dplyr,你可以这样做:

1.Arrange() 按标签和 dimension_r.

2.lag() 列并过滤掉 NA.

3.rename() 所需名称的列 ID。

4.select() 所需的列。

library(dplyr)
MyData %>% group_by(Tag)%>%arrange(Tag,dimension_r) %>% 
      mutate(lower = lag(id))%>% 
      filter(!is.na(lower))%>%
      rename(greater = id) %>%
      select(Tag, lower, greater)
# # A tibble: 8 x 3
# # Groups:   Tag [2]
# Tag   lower greater
# <chr> <int>   <int>
# 1 Tag1  16368   15121
# 2 Tag1  15121   15122
# 3 Tag1  15122   15123
# 4 Tag1  15123   15124
# 5 Tag1  15124   15125
# 6 Tag1  15125   15227
# 7 Tag2  15391   15392
# 8 Tag2  15392   15393