假设一个像这样的数据框:
# example dataset
df <- data.frame(
rowid = 1:3,
a = c("ax","cz","by"),
b = c("cy","ax","bz"),
c = c("bz","ay","cx")
)
实现以下转型的有效方法是什么?
#> # A tibble: 3 x 4
#> rowid a b c
#> <int> <chr> <chr> <chr>
#> 1 x z y
#> 2 x y z
#> 3 y z x
目标是获取每个二元组的第二个字符,并将其按每行的第一个字符挑选的列进行排序。
如果可能,比较基本 R 和 Tidyverse 解决方案会很有用。
最佳答案
由于您正在寻找 Base 和 Tidyverse 的比较,我将提供一个基本解决方案:
tdf <- t(df[-1])
tdf[] <- substr(tdf, 2, 2)[order(col(tdf), tdf)]
df[-1] <- t(tdf)
# rowid a b c
#1 1 x z y
#2 2 x y z
#3 3 y z x
解释这 3 个步骤:
.1) 获取 t()
的副本数据的转置版本
.2a) 获取order
在每个字符串(隐式地第一个字母)的每一行( col()
现在,因为它被转置)
.2b) 使用此顺序从每个字符串的第二个字母中进行选择并覆盖 <-
转置后的数据。
.3) t()
转回原始结构并覆盖 <-
df
中的数据
30K 行基准
基础:
bigdf <- df[rep(1:3,10000),]
bigdf$rowid <- 1:30000
system.time({
tdf <- t(bigdf[-1])
tdf[] <- substr(tdf,2,2)[order(col(tdf), tdf)]
bigdf[-1] <- t(tdf)
})
## user system elapsed
## 0.023 0.000 0.023
整洁:
bigdf <- df[rep(1:3,10000),]
bigdf$rowid <- 1:30000
library(dplyr)
library(tibble)
library(sjmisc)
library(stringr)
system.time({
bigdf %>%
rotate_df(cn=TRUE) %>%
mutate(across(everything(),sort)) %>%
rotate_df() %>%
mutate(across(everything(),~str_sub(.,2,-1))) %>%
rownames_to_column(var="rowid")
})
## user system elapsed
## 21.177 0.047 21.244
关于r - 如何将二元组拆分为 n 列的列对和行对,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70970271/