根据 r 中的另一个索引值按组重新排序行
reorder rows by group based on another index value in r
Base R 中是否有一种方法可以根据列值按组对数据进行重新排序?
例如,如果我有一个数据集 m:
name v1 v2 v3
a1 4 1 2
a2 1 3 2
a3 1 5 2
b1 1 2 2
b2 1 4 2
b3 1 3 2
c1 6 1 2
c2 5 1 2
c3 4 1 2
而且我每个组都有另一个索引向量,这意味着如果我的数据有 3 个组 a、b、c,这个索引向量只有 3 行:
2个
3个
1
现在我想根据这个索引向量(升序,1、2、3)对我的数据集重新排序,所以组的顺序应该是 c、a、b,但是组内的顺序没有变化,比如下面:
name v1 v2 v3
c1 6 1 2
c2 5 1 2
c3 4 1 2
a1 4 1 2
a2 1 3 2
a3 1 5 2
b1 1 2 2
b2 1 4 2
b3 1 3 2
有没有办法在 Base R 中做到这一点?谢谢!
一个选项是在 factor
转换后的 'name' 列上使用 arrange
,删除数字并在自定义订单中指定 levels
或 'c' , 'a', 'b'
library(dplyr)
df1 %>%
arrange(factor(sub("\d+", "", name), levels = c("c", "a", "b")))
-输出
# name v1 v2 v3
#1 c1 6 1 2
#2 c2 5 1 2
#3 c3 4 1 2
#4 a1 4 1 2
#5 a2 1 3 2
#6 a3 1 5 2
#7 b1 1 2 2
#8 b2 1 4 2
#9 b3 1 3 2
或仅在 base R
中使用相同的语法
df1[order(with(df1, factor(sub("\d+", "", name), levels = c('c', 'a', 'b')))), ]
# name v1 v2 v3
#7 c1 6 1 2
#8 c2 5 1 2
#9 c3 4 1 2
#1 a1 4 1 2
#2 a2 1 3 2
#3 a3 1 5 2
#4 b1 1 2 2
#5 b2 1 4 2
#6 b3 1 3 2
数据
df1 <- structure(list(name = c("a1", "a2", "a3", "b1", "b2", "b3", "c1",
"c2", "c3"), v1 = c(4L, 1L, 1L, 1L, 1L, 1L, 6L, 5L, 4L), v2 = c(1L,
3L, 5L, 2L, 4L, 3L, 1L, 1L, 1L), v3 = c(2L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 2L)), class = "data.frame", row.names = c(NA, -9L))
假设您有一个命名索引向量 v
,
v <- c(a=2, b=3, c=1)
在 base R 中,您可以使用 match
按以下方式创建临时 id
列,然后 order
您的结果。
ds1$id <- v[match(substr(ds1$name, 1, 1), names(v))]
ds1[order(ds1$id), -5]
# name v1 v2 v3
# 7 c1 6 1 2
# 8 c2 5 1 2
# 9 c3 4 1 2
# 1 a1 4 1 2
# 2 a2 1 3 2
# 3 a3 1 5 2
# 4 b1 1 2 2
# 5 b2 1 4 2
# 6 b3 1 3 2
如果没有 "name"
列,您可以 split
seq
个长度为 n
、sample
和 rbind
的行回到一起。
ds2 <- ds1[2:4] ## generate data w/o "name" column
n <- 3
do.call(rbind, sample(split(ds2, rep(seq(nrow(ds2)/n), each=n))))
# v1 v2 v3
# 3.7 6 1 2
# 3.8 5 1 2
# 3.9 4 1 2
# 1.1 4 1 2
# 1.2 1 3 2
# 1.3 1 5 2
# 2.4 1 2 2
# 2.5 1 4 2
# 2.6 1 3 2
除以 n
有余数,与 n=4
的情况一样,您会收到警告,多余的行会分配给其他组。不知道这些对你是否足够?
数据
ds1 <- structure(list(name = c("a1", "a2", "a3", "b1", "b2", "b3", "c1",
"c2", "c3"), v1 = c(4L, 1L, 1L, 1L, 1L, 1L, 6L, 5L, 4L), v2 = c(1L,
3L, 5L, 2L, 4L, 3L, 1L, 1L, 1L), v3 = c(2L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 2L), id = c(2, 2, 2, 3, 3, 3, 1, 1, 1)), row.names = c(NA,
-9L), class = "data.frame")
仅使用 base R
你需要一个关键数据框来存储你的向量:
#Code
keys <- data.frame(name=c('a','b','c'),order=c(2,3,1),stringsAsFactors = F)
#Add
df$Index <- keys[match(substring(df$name,1,1),keys$name),"order"]
df <- df[order(df$Index),]
df$Index <- NULL
输出:
df
name v1 v2 v3
7 c1 6 1 2
8 c2 5 1 2
9 c3 4 1 2
1 a1 4 1 2
2 a2 1 3 2
3 a3 1 5 2
4 b1 1 2 2
5 b2 1 4 2
6 b3 1 3 2
使用了一些数据:
#Data
df <- structure(list(name = c("a1", "a2", "a3", "b1", "b2", "b3", "c1",
"c2", "c3"), v1 = c(4L, 1L, 1L, 1L, 1L, 1L, 6L, 5L, 4L), v2 = c(1L,
3L, 5L, 2L, 4L, 3L, 1L, 1L, 1L), v3 = c(2L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 2L)), class = "data.frame", row.names = c(NA, -9L))
顺序必须基于任何感兴趣的列。如果要根据变量 v1 排序,则:
dad <- data.frame(names = paste0(rep(letters[1:3],rep(3,3)),1:3),v1=rnorm(9),v2=rnorm(9))
dad[order(dad$v1),]
Base R 中是否有一种方法可以根据列值按组对数据进行重新排序? 例如,如果我有一个数据集 m:
name v1 v2 v3
a1 4 1 2
a2 1 3 2
a3 1 5 2
b1 1 2 2
b2 1 4 2
b3 1 3 2
c1 6 1 2
c2 5 1 2
c3 4 1 2
而且我每个组都有另一个索引向量,这意味着如果我的数据有 3 个组 a、b、c,这个索引向量只有 3 行: 2个 3个 1
现在我想根据这个索引向量(升序,1、2、3)对我的数据集重新排序,所以组的顺序应该是 c、a、b,但是组内的顺序没有变化,比如下面:
name v1 v2 v3
c1 6 1 2
c2 5 1 2
c3 4 1 2
a1 4 1 2
a2 1 3 2
a3 1 5 2
b1 1 2 2
b2 1 4 2
b3 1 3 2
有没有办法在 Base R 中做到这一点?谢谢!
一个选项是在 factor
转换后的 'name' 列上使用 arrange
,删除数字并在自定义订单中指定 levels
或 'c' , 'a', 'b'
library(dplyr)
df1 %>%
arrange(factor(sub("\d+", "", name), levels = c("c", "a", "b")))
-输出
# name v1 v2 v3
#1 c1 6 1 2
#2 c2 5 1 2
#3 c3 4 1 2
#4 a1 4 1 2
#5 a2 1 3 2
#6 a3 1 5 2
#7 b1 1 2 2
#8 b2 1 4 2
#9 b3 1 3 2
或仅在 base R
df1[order(with(df1, factor(sub("\d+", "", name), levels = c('c', 'a', 'b')))), ]
# name v1 v2 v3
#7 c1 6 1 2
#8 c2 5 1 2
#9 c3 4 1 2
#1 a1 4 1 2
#2 a2 1 3 2
#3 a3 1 5 2
#4 b1 1 2 2
#5 b2 1 4 2
#6 b3 1 3 2
数据
df1 <- structure(list(name = c("a1", "a2", "a3", "b1", "b2", "b3", "c1",
"c2", "c3"), v1 = c(4L, 1L, 1L, 1L, 1L, 1L, 6L, 5L, 4L), v2 = c(1L,
3L, 5L, 2L, 4L, 3L, 1L, 1L, 1L), v3 = c(2L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 2L)), class = "data.frame", row.names = c(NA, -9L))
假设您有一个命名索引向量 v
,
v <- c(a=2, b=3, c=1)
在 base R 中,您可以使用 match
按以下方式创建临时 id
列,然后 order
您的结果。
ds1$id <- v[match(substr(ds1$name, 1, 1), names(v))]
ds1[order(ds1$id), -5]
# name v1 v2 v3
# 7 c1 6 1 2
# 8 c2 5 1 2
# 9 c3 4 1 2
# 1 a1 4 1 2
# 2 a2 1 3 2
# 3 a3 1 5 2
# 4 b1 1 2 2
# 5 b2 1 4 2
# 6 b3 1 3 2
如果没有 "name"
列,您可以 split
seq
个长度为 n
、sample
和 rbind
的行回到一起。
ds2 <- ds1[2:4] ## generate data w/o "name" column
n <- 3
do.call(rbind, sample(split(ds2, rep(seq(nrow(ds2)/n), each=n))))
# v1 v2 v3
# 3.7 6 1 2
# 3.8 5 1 2
# 3.9 4 1 2
# 1.1 4 1 2
# 1.2 1 3 2
# 1.3 1 5 2
# 2.4 1 2 2
# 2.5 1 4 2
# 2.6 1 3 2
除以 n
有余数,与 n=4
的情况一样,您会收到警告,多余的行会分配给其他组。不知道这些对你是否足够?
数据
ds1 <- structure(list(name = c("a1", "a2", "a3", "b1", "b2", "b3", "c1",
"c2", "c3"), v1 = c(4L, 1L, 1L, 1L, 1L, 1L, 6L, 5L, 4L), v2 = c(1L,
3L, 5L, 2L, 4L, 3L, 1L, 1L, 1L), v3 = c(2L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 2L), id = c(2, 2, 2, 3, 3, 3, 1, 1, 1)), row.names = c(NA,
-9L), class = "data.frame")
仅使用 base R
你需要一个关键数据框来存储你的向量:
#Code
keys <- data.frame(name=c('a','b','c'),order=c(2,3,1),stringsAsFactors = F)
#Add
df$Index <- keys[match(substring(df$name,1,1),keys$name),"order"]
df <- df[order(df$Index),]
df$Index <- NULL
输出:
df
name v1 v2 v3
7 c1 6 1 2
8 c2 5 1 2
9 c3 4 1 2
1 a1 4 1 2
2 a2 1 3 2
3 a3 1 5 2
4 b1 1 2 2
5 b2 1 4 2
6 b3 1 3 2
使用了一些数据:
#Data
df <- structure(list(name = c("a1", "a2", "a3", "b1", "b2", "b3", "c1",
"c2", "c3"), v1 = c(4L, 1L, 1L, 1L, 1L, 1L, 6L, 5L, 4L), v2 = c(1L,
3L, 5L, 2L, 4L, 3L, 1L, 1L, 1L), v3 = c(2L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 2L)), class = "data.frame", row.names = c(NA, -9L))
顺序必须基于任何感兴趣的列。如果要根据变量 v1 排序,则:
dad <- data.frame(names = paste0(rep(letters[1:3],rep(3,3)),1:3),v1=rnorm(9),v2=rnorm(9))
dad[order(dad$v1),]