R语言 当df目标单元格的值不为NA时,如何合并df的行和列名

r7xajy2e  于 2023-07-31  发布在  其他
关注(0)|答案(4)|浏览(102)

我有一个这样的df:

df1 <- data.frame(c(3,NA,5), c(NA, NA, 3), c(3, 2, NA))
names(df1) <- c('number1', 'number2', 'number3')
rownames(df1) <- c('siteA', 'siteB', 'siteC')

字符串
我想做一个新的df,其中行和列名是由不NA的值组合而成的。生成的df应该如下所示:

df2 <- data.frame('number' = c('number1', 'number1', 'number2', 'number3', 'number3'), 
                  'site' = c('siteA', 'siteC', 'siteC', 'siteA', 'siteB'))


我如何尽可能高效地做到这一点?(我的真实的df是巨大的)

slwdgvem

slwdgvem1#

在矩阵或表格中,每个轴可以具有名称,该名称是标记该轴的字符串。将df1转换为矩阵m并将它们相加。
然后使用as.data.frame.table将其转换为长格式,并删除NA的行。as.data.frame.table将添加名为Freq的第三列,这是我们不需要的,因此只选择前2列,并且由于问题将数字放在第一位,因此将提取的两列的顺序颠倒。

m <- as.matrix(df1)
 names(dimnames(m)) <- c("site", "number")

 m |>
  as.data.frame.table() |>
  na.omit() |>
  subset(select = 2:1)
##    number  site
## 1 number1 siteA
## 3 number1 siteC
## 6 number2 siteC
## 7 number3 siteA
## 8 number3 siteB

字符串
m看起来像这样。注意dimnames。

m
##        number
## site    number1 number2 number3
##   siteA       3      NA       3
##   siteB      NA      NA       2
##   siteC       5       3      NA

7ajki6be

7ajki6be2#

使用tidyverse的简单方法:

df1 %>% 
    rownames_to_column('site') %>%
    pivot_longer(-site, names_to = 'number', values_to = 'value') %>%
    filter(!is.na(value)) %>%
    select(-value)

字符串

s3fp2yjn

s3fp2yjn3#

你也可以在这里使用which()。首先,你找到data.frame中没有丢失的行(不需要先将其转换为矩阵),然后用arr.ind = TRUE得到索引。这些索引是具有非NA值的数据的行和列。这样做的另一个好处是row.names将是原始data.frame的row.names。我将矩阵输出转换为具有正确变量名的data.frame,然后将列和行名称中的值分配给数字。

df2 <- which(!is.na(df1), arr.ind = TRUE)

df2 <- data.frame(number =colnames(df1)[df2[,2]] , site = row.names(df2))

字符串
乐趣基准:

transform_fn <- function(){
  m <- as.matrix(df1)
  names(dimnames(m)) <- c("site", "number")
  
  m |>
    t() |>
    as.data.frame.table() |>
    na.omit() |>
    subset(select = 1:2)
}

which_fn <- function(){
df2 <- which(!is.na(df1), arr.ind = TRUE)

 data.frame(number =colnames(df1)[df2[,2]] , site = row.names(df2))
}

tidyverse_fn <- function(){df1 %>% 
  rownames_to_column('site') %>%
  pivot_longer(-site, names_to = 'number', values_to = 'value') %>%
  filter(!is.na(value)) %>%
  select(-value)
}

microbenchmark::microbenchmark(which_fn(),transform_fn(),tidyverse_fn(),
                               times = 1000)


的数据

wh6knrhe

wh6knrhe4#

我们可以尝试expand.grid + dimnames

> rev(expand.grid(dimnames(df1)))[!is.na(unlist(df1)), ]
     Var2  Var1
1 number1 siteA
3 number1 siteC
6 number2 siteC
7 number3 siteA
8 number3 siteB

字符串

相关问题