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
基于 Tag
和 dimension_r
的数据。我们根据 Tag
拆分 newdata
并通过分别忽略最后和第一个观察来创建 lower
和 greater
列。
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
我们可以使用 dplyr
和 purrr::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
我有以下数据框,其 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
基于 Tag
和 dimension_r
的数据。我们根据 Tag
拆分 newdata
并通过分别忽略最后和第一个观察来创建 lower
和 greater
列。
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
我们可以使用 dplyr
和 purrr::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