Существует ли эквивалентная функция R команде Stata 'order'?
'order' в R кажется "сортировкой" в Stata. Например, набор данных (только имена переменных):
v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18
и здесь ожидаемый результат:
v1 v2 v3 v4 v5 v7 v8 v9 v10 v11 v12 v17 v18 v13 v14 v15 v6 v16
В R у меня есть 2 способа:
data <- data[,c(1:5,7:12,17:18,13:15,6,16)]
ИЛИ
names <- c("v1", "v2", "v3", "v4", "v5", "v7", "v8", "v9", "v10", "v11", "v12", "v17", "v18", "v13", "v14", "v15", "v6", "v16")
data <- data[names]
Чтобы получить тот же результат в Stata, я могу запустить 2 строки:
order v17 v18, before(v13)
order v6 v16, last
В идеальных данных выше мы можем знать положения переменных, с которыми мы хотим иметь дело. Но в большинстве реальных случаев у нас есть переменные, такие как "возраст" "пол" без индикаторов позиции, и у нас может быть более 50 переменных в одном наборе данных. Тогда преимущество "порядка" в Стате может быть более очевидным. Нам не нужно знать точное место переменной и просто введите его имя:
order age, after(gender)
Есть ли базовая функция в R для решения этой проблемы или я могу получить пакет? Спасибо заранее.
tweetinfo <- data.frame(uid=1:50, mid=2:51, annotations=3:52, bmiddle_pic=4:53, created_at=5:54, favorited=6:55, geo=7:56, in_reply_to_screen_name=8:57, in_reply_to_status_id=9:58, in_reply_to_user_id=10:59, original_pic=11:60, reTweetId=12:61, reUserId=13:62, source=14:63, thumbnail_pic=15:64, truncated=16:65)
noretweetinfo <- data.frame(uid=21:50, mid=22:51, annotations=23:52, bmiddle_pic=24:53, created_at=25:54, favorited=26:55, geo=27:56, in_reply_to_screen_name=28:57, in_reply_to_status_id=29:58, in_reply_to_user_id=30:59, original_pic=31:60, reTweetId=32:61, reUserId=33:62, source=34:63, thumbnail_pic=35:64, truncated=36:65)
retweetinfo <- data.frame(uid=41:50, mid=42:51, annotations=43:52, bmiddle_pic=44:53, created_at=45:54, deleted=46:55, favorited=47:56, geo=48:57, in_reply_to_screen_name=49:58, in_reply_to_status_id=50:59, in_reply_to_user_id=51:60, original_pic=52:61, source=53:62, thumbnail_pic=54:63, truncated=55:64)
tweetinfo$type <- "ti"
noretweetinfo$type <- "nr"
retweetinfo$type <- "rt"
gtinfo <- rbind(tweetinfo, noretweetinfo)
gtinfo$deleted=""
gtinfo <- gtinfo[,c(1:16,18,17)]
retweetinfo <- transform(retweetinfo, reTweetId="", reUserId="")
retweetinfo <- retweetinfo[,c(1:5,7:12,17:18,13:15,6,16)]
gtinfo <- rbind(gtinfo, retweetinfo)
write.table(gtinfo, file="C:/gtinfo.txt", row.names=F, col.names=T, sep="\t", quote=F)
# rm(list=ls(all=T))
Ответы
Ответ 1
Потому что я затягиваю и экспериментирую с разными вещами, вот функция, которую я взбивал. В конечном счете, это зависит от append
:
moveme <- function(invec, movecommand) {
movecommand <- lapply(strsplit(strsplit(movecommand, ";")[[1]], ",|\\s+"),
function(x) x[x != ""])
movelist <- lapply(movecommand, function(x) {
Where <- x[which(x %in% c("before", "after", "first", "last")):length(x)]
ToMove <- setdiff(x, Where)
list(ToMove, Where)
})
myVec <- invec
for (i in seq_along(movelist)) {
temp <- setdiff(myVec, movelist[[i]][[1]])
A <- movelist[[i]][[2]][1]
if (A %in% c("before", "after")) {
ba <- movelist[[i]][[2]][2]
if (A == "before") {
after <- match(ba, temp)-1
} else if (A == "after") {
after <- match(ba, temp)
}
} else if (A == "first") {
after <- 0
} else if (A == "last") {
after <- length(myVec)
}
myVec <- append(temp, values = movelist[[i]][[1]], after = after)
}
myVec
}
Вот несколько примеров данных, представляющих имена вашего набора данных:
x <- paste0("v", 1:18)
Представьте себе, что мы хотели "v17" и "v18" перед "v3", "v6" и "v16" в конце и "v5" в начале:
moveme(x, "v17, v18 before v3; v6, v16 last; v5 first")
# [1] "v5" "v1" "v2" "v17" "v18" "v3" "v4" "v7" "v8" "v9" "v10" "v11" "v12"
# [14] "v13" "v14" "v15" "v6" "v16"
Таким образом, очевидное использование было бы для data.frame
с именем "df":
df[moveme(names(df), "how you want to move the columns")]
И для a data.table
с именем "DT" (который, как указывает @mnel, будет более эффективным с точки зрения памяти):
setcolorder(DT, moveme(names(DT), "how you want to move the columns"))
Обратите внимание, что составные перемещения задаются точками с запятой.
Признанные ходы:
-
before
(переместите указанные столбцы до другого столбца с именем)
-
after
(переместите указанные столбцы на другой столбец с именем)
-
first
(переместите указанные столбцы в первую позицию)
-
last
(переместите указанные столбцы в последнюю позицию)
Ответ 2
Я получаю вашу проблему. Теперь у меня есть код:
move <- function(data,variable,before) {
m <- data[variable]
r <- data[names(data)!=variable]
i <- match(before,names(data))
pre <- r[1:i-1]
post <- r[i:length(names(r))]
cbind(pre,m,post)
}
# Example.
library(MASS)
data(painters)
str(painters)
# Move 'Expression' variable before 'Drawing' variable.
new <- move(painters,"Expression","Drawing")
View(new)
Ответ 3
Вы можете написать свою собственную функцию, которая сделает это.
Следующее даст вам новый порядок имен ваших столбцов, используя аналогичный синтаксис для statap >
Функция работает только с именами (как только вы передаете объект data.frame
как data
) и возвращает переупорядоченный список имен
например,
stata.order <- function(var_list, where, sorted = F, data) {
all_names = names(data)
# are all the variable names in
check <- var_list %in% all_names
if (any(!check)) {
stop("Not all variables in var_list exist within data")
}
if (names(where) == "before") {
if (!(where %in% all_names)) {
stop("before variable not in the data set")
}
}
if (names(where) == "after") {
if (!(where %in% all_names)) {
stop("after variable not in the data set")
}
}
if (sorted) {
var_list <- sort(var_list)
}
where_in <- which(all_names %in% var_list)
full_list <- seq_along(data)
others <- full_list[-c(where_in)]
.nwhere <- names(where)
if (!(.nwhere %in% c("last", "first", "before", "after"))) {
stop("where must be a list of a named element first, last, before or after")
}
do_what <- switch(names(where), last = length(others), first = 0, before = which(all_names[others] ==
where) - 1, after = which(all_names[others] == where))
new_order <- append(others, where_in, do_what)
return(all_names[new_order])
}
tmp <- as.data.frame(matrix(1:100, ncol = 10))
stata.order(var_list = c("V2", "V5"), where = list(last = T), data = tmp)
## [1] "V1" "V3" "V4" "V6" "V7" "V8" "V9" "V10" "V2" "V5"
stata.order(var_list = c("V2", "V5"), where = list(first = T), data = tmp)
## [1] "V2" "V5" "V1" "V3" "V4" "V6" "V7" "V8" "V9" "V10"
stata.order(var_list = c("V2", "V5"), where = list(before = "V6"), data = tmp)
## [1] "V1" "V3" "V4" "V2" "V5" "V6" "V7" "V8" "V9" "V10"
stata.order(var_list = c("V2", "V5"), where = list(after = "V4"), data = tmp)
## [1] "V1" "V3" "V4" "V2" "V5" "V6" "V7" "V8" "V9" "V10"
# throws an error
stata.order(var_list = c("V2", "V5"), where = list(before = "v11"), data = tmp)
## Error: before variable not in the data set
если вы хотите эффективно выполнять переупорядочивание памяти (по ссылке, без копирования) используйте data.table
DT <- data.table(tmp)
# sets by reference, no copying
setcolorder(DT, stata.order(var_list = c("V2", "V5"), where = list(after = "V4"),
data = DT))
DT
## V1 V3 V4 V2 V5 V6 V7 V8 V9 V10
## 1: 1 21 31 11 41 51 61 71 81 91
## 2: 2 22 32 12 42 52 62 72 82 92
## 3: 3 23 33 13 43 53 63 73 83 93
## 4: 4 24 34 14 44 54 64 74 84 94
## 5: 5 25 35 15 45 55 65 75 85 95
## 6: 6 26 36 16 46 56 66 76 86 96
## 7: 7 27 37 17 47 57 67 77 87 97
## 8: 8 28 38 18 48 58 68 78 88 98
## 9: 9 29 39 19 49 59 69 79 89 99
## 10: 10 30 40 20 50 60 70 80 90 100
Ответ 4
Непонятно, что вы хотели бы сделать, но ваше первое предложение заставляет меня предположить, что вы хотите сортировать набор данных.
На самом деле существует встроенная функция order
, которая возвращает индексы упорядоченной последовательности. Вы ищете это?
> x <- c(3,2,1)
> order(x)
[1] 3 2 1
> x[order(x)]
[1] 1 2 3
Ответ 5
Это даст вам тот же файл:
#snip
gtinfo <- rbind(tweetinfo, noretweetinfo)
gtinfo$deleted=""
retweetinfo <- transform(retweetinfo, reTweetId="", reUserId="")
gtinfo <- rbind(gtinfo, retweetinfo)
gtinfo <-gtinfo[,c(1:16,18,17)]
#snip
В R можно реализовать такую функцию, как функция порядка Strata, но я не думаю, что для этого существует большая потребность.