返回仅满足数值变量条件的变量名

问题描述 投票:0回答:3

我试图在我的数据框中创建一个新变量,它返回满足条件的变量名称,但是我在数据集上也有一个chr变量,因此必须应用某种数字包装器。

数据集之前:

          ChrV   |   V1  |   V2  |   V3       
 Obs 1 |  chr1   |  0.65 |  0.30 |  0.40
 Obs 2 |  chr2   |  0.35 |  0.75 |  0.42
 Obs 3 |  chr3   |  0.10 |  0.43 |  0.80

我的解决方案

  • 保存chr变量。 ChrV <- ds$ChrV
  • 从数据集中删除chr变量(替代数字包装器) ds$ChrV <- NULL
  • 创建新列 - 应用于数据集的所有行:function - 粘贴x的绝对值大于等于0.5的列名。 ds$V4 <- apply(ds, 1, function(x) paste(names(which(abs(x) >= 0.5))))
  • 将chr变量绑定回数据集。 ds <- cbind(ChrV, ds)

输出:

          ChrV   |   V1  |   V2  |   V2  |   V4       
 Obs 1 |  chr1   |  0.65 |  0.30 |  0.40 |  Var 1
 Obs 2 |  chr2   |  0.35 |  0.75 |  0.42 |  Var 2
 Obs 3 |  chr3   |  0.10 |  0.43 |  0.80 |  Var 3

我的问题:

虽然我的解决方案有效,但我需要找到一个忽略chr变量的更优雅的解决方案(因此它只考虑数值变量,我不需要删除变量并在以后再次绑定它们),这也适用于任何数据集,无论列数和行数。

dput(DS)

structure(list(
ChrV = c("chr1", "chr2", "chr3"), 
V1 = c(3, 2, 1), 
V2 = c(1, 3, 2), 
V3 = c(1, 2, 3)), 
row.names = c(NA, -6L), 
class = c("data.table", "data.frame"),
 .internal.selfref = <pointer: 0x0000000002541ef0>)   
r condition apply sapply which
3个回答
1
投票

如果tidyverse解决方案可以接受,您可以按以下方式执行:

library(tidyverse)

df %>%
  rownames_to_column() %>%
  gather(cname, val, V1:V3) %>%
  group_by(ChrV) %>%
  mutate(V4 = cname[abs(as.numeric(val)) >= .5] %>% str_c(collapse = ' ')) %>%
  spread(cname, val)

1
投票

你仍然可以用max.col做到这一点

ds$V4 <- paste("Var", max.col(abs(ds[2:4]) > 0.5))

df
#     ChrV   V1   V2   V3    V4
#Obs1 chr1 0.65 0.30 0.40 Var 1
#Obs2 chr2 0.35 0.75 0.42 Var 2
#Obs3 chr3 0.10 0.43 0.80 Var 3

或者,如果您想要列名称

ds$V4 <- names(ds)[2:4][max.col(abs(ds[2:4]) > 0.5)]

如果您想以动态方式仅选择数字列,我们可以使用@markus建议的Filter

new_ds <- Filter(is.numeric, ds)
ds$V4 <- names(new_ds)[max.col(abs(new_ds) > 0.5)]

1
投票

您可以在apply函数中对数据框进行子集化:

ds$V4 <- apply(ds[colnames(ds) != "ChrV"], 1, function(x) 
paste(names(which(abs(x) >= 0.5))))

编辑

对于类data.frame,删除粘贴并对apply的输出进行子集化:

> ds <- data.frame(
+   ChrV = c("chr1", "chr2", "chr3"), 
+   V1 = c(3, 2, 1), 
+   V2 = c(1, 3, 2), 
+   V3 = c(1, 2, 3))
> 
> 
> ds$V4 <- apply(ds[colnames(ds) != "ChrV"], 1, function(x) {
+   names(which(abs(x) >= 0.5))
+ })[,1]
> 
> ds
  ChrV V1 V2 V3 V4
1 chr1  3  1  1 V1
2 chr2  2  3  2 V2
3 chr3  1  2  3 V3
> 

再见!

© www.soinside.com 2019 - 2024. All rights reserved.