Is er een eenvoudigere manier om ervoor te zorgen dat de rijen van een dataframe worden geordend volgens een “doel”-vector zoals die ik in het korte voorbeeld hieronder heb geïmplementeerd?
df <- data.frame(name = letters[1:4], value = c(rep(TRUE, 2), rep(FALSE, 2)))
df
# name value
# 1 a TRUE
# 2 b TRUE
# 3 c FALSE
# 4 d FALSE
target <- c("b", "c", "a", "d")
Dit lijkt op de een of andere manier een beetje te “gecompliceerd” om de klus te klaren:
idx <- sapply(target, function(x) {
which(df$name == x)
})
df <- df[idx,]
rownames(df) <- NULL
df
# name value
# 1 b TRUE
# 2 c FALSE
# 3 a TRUE
# 4 d FALSE
Antwoord 1, autoriteit 100%
Probeer match
:
df <- data.frame(name=letters[1:4], value=c(rep(TRUE, 2), rep(FALSE, 2)))
target <- c("b", "c", "a", "d")
df[match(target, df$name),]
name value
2 b TRUE
3 c FALSE
1 a TRUE
4 d FALSE
Het werkt zolang uw target
exact dezelfde elementen bevat als df$name
en geen van beide dubbele waarden bevat.
Van ?match
:
match returns a vector of the positions of (first) matches of its first argument
in its second.
Daarom vindt match
de rijnummers die overeenkomen met de elementen van target
, en dan retourneren we df
in die volgorde.
Antwoord 2, autoriteit 11%
Ik gebruik liever ***_join
in dplyr
wanneer ik gegevens moet matchen. Een mogelijke poging hiervoor
left_join(data.frame(name=target),df,by="name")
Houd er rekening mee dat de invoer voor ***_join
tbls of data.frame vereist
Antwoord 3, autoriteit 9%
We kunnen de factorniveaus aanpassen op basis van target
en deze gebruiken in arrange
library(dplyr)
df %>% arrange(factor(name, levels = target))
# name value
#1 b TRUE
#2 c FALSE
#3 a TRUE
#4 d FALSE
Of order
het en gebruik het in slice
df %>% slice(order(factor(name, levels = target)))
Antwoord 4, autoriteit 7%
Deze methode is een beetje anders, het gaf me wat meer flexibiliteit dan het vorige antwoord.
Door er een geordende factor van te maken, kun je het mooi gebruiken in arrange
en dergelijke. Ik heb reorder.factor uit het pakket gdata
gebruikt.
df <- data.frame(name=letters[1:4], value=c(rep(TRUE, 2), rep(FALSE, 2)))
target <- c("b", "c", "a", "d")
require(gdata)
df$name <- reorder.factor(df$name, new.order=target)
Gebruik vervolgens het feit dat het nu besteld is:
require(dplyr)
df %>%
arrange(name)
name value
1 b TRUE
2 c FALSE
3 a TRUE
4 d FALSE
Als je terug wilt naar de oorspronkelijke (alfabetische) volgorde, gebruik je gewoon as.character()
om het terug te brengen naar de oorspronkelijke staat.
Antwoord 5
Als je geen bibliotheken wilt gebruiken en je hebt herhalingen in je gegevens, dan kun je which
ook gebruiken met sapply
.
new_order <- sapply(target, function(x,df){which(df$name == x)}, df=df)
df <- df[new_order,]
Antwoord 6
Hier is een soortgelijk systeem voor de situatie waarin u een variabele hebt waarop u aanvankelijk wilt sorteren, maar vervolgens wilt sorteren op een secundaire variabele volgens de volgorde waarin deze secundaire variabele voor het eerst voorkomt bij de eerste sortering.
p>
In de onderstaande functie wordt de initiële sorteervariabele order_by
genoemd en de secundaire variabele order_along
– zoals in “volgorde op deze variabele in de beginvolgorde”.
library(dplyr, warn.conflicts = FALSE)
df <- structure(
list(
msoa11hclnm = c(
"Bewbush", "Tilgate", "Felpham",
"Selsey", "Brunswick", "Ratton", "Ore", "Polegate", "Mile Oak",
"Upperton", "Arundel", "Kemptown"
),
lad20nm = c(
"Crawley", "Crawley",
"Arun", "Chichester", "Brighton and Hove", "Eastbourne", "Hastings",
"Wealden", "Brighton and Hove", "Eastbourne", "Arun", "Brighton and Hove"
),
shape_area = c(
1328821, 3089180, 3540014, 9738033, 448888, 10152663, 5517102,
7036428, 5656430, 2653589, 72832514, 826151
)
),
row.names = c(NA, -12L), class = "data.frame"
)
dit geeft me niet wat ik nodig heb:
df %>%
dplyr::arrange(shape_area, lad20nm)
#> msoa11hclnm lad20nm shape_area
#> 1 Brunswick Brighton and Hove 448888
#> 2 Kemptown Brighton and Hove 826151
#> 3 Bewbush Crawley 1328821
#> 4 Upperton Eastbourne 2653589
#> 5 Tilgate Crawley 3089180
#> 6 Felpham Arun 3540014
#> 7 Ore Hastings 5517102
#> 8 Mile Oak Brighton and Hove 5656430
#> 9 Polegate Wealden 7036428
#> 10 Selsey Chichester 9738033
#> 11 Ratton Eastbourne 10152663
#> 12 Arundel Arun 72832514
Hier is een functie:
order_along <- function(df, order_along, order_by) {
cols <- colnames(df)
df <- df %>%
dplyr::arrange({{ order_by }})
df %>%
dplyr::select({{ order_along }}) %>%
dplyr::distinct() %>%
dplyr::full_join(df) %>%
dplyr::select(dplyr::all_of(cols))
}
order_along(df, lad20nm, shape_area)
#> Joining, by = "lad20nm"
#> msoa11hclnm lad20nm shape_area
#> 1 Brunswick Brighton and Hove 448888
#> 2 Kemptown Brighton and Hove 826151
#> 3 Mile Oak Brighton and Hove 5656430
#> 4 Bewbush Crawley 1328821
#> 5 Tilgate Crawley 3089180
#> 6 Upperton Eastbourne 2653589
#> 7 Ratton Eastbourne 10152663
#> 8 Felpham Arun 3540014
#> 9 Arundel Arun 72832514
#> 10 Ore Hastings 5517102
#> 11 Polegate Wealden 7036428
#> 12 Selsey Chichester 9738033
Gemaakt op 2021-01-12 door het reprex-pakket(v0.3.0) sup>