【问题标题】:Return variable name which satisfies condition on numeric variables only返回仅满足数值变量条件的变量名
【发布时间】:2019-08-02 21:21:51
【问题描述】:

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

之前的数据集:

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

我的解决方案:

  • 保存 chr 变量。

    ChrV <- ds$ChrV
    
  • 从数据集中删除 chr 变量(替代数字包装器)

    ds$ChrV <- NULL
    
  • 创建新列 - 应用于数据集的所有行:函数 - 粘贴 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
 观察 1 | chr1 | 0.65 | 0.30 | 0.40 | 变量 1
 观察 2 | chr2 | 0.35 | 0.75 | 0.42 | 变量 2
 观察 3 | chr3 | 0.10 | 0.43 | 0.80 | 变量 3

我的问题:

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

输入(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>)   

【问题讨论】:

  • 你想要每行的最大值索引吗? max.col(df[2:4]) ?
  • @RonakShah 否,特别是大于等于 0.5 的绝对值
  • @Seni 如果有多个值,预期的输出是什么> | 0.5 |每行?
  • @markus 不应该发生,但如果发生了,那么 NA

标签: r conditional-statements apply sapply


【解决方案1】:

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

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

编辑

对于 data.frame 类,删除 paste 并对 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
> 

再见!

【讨论】:

  • 谢谢,但它返回 - [.data.table(ds, colnames(ds) != "ChrV") 中的错误:i 计算为逻辑向量长度 5 但有 6 行。不再允许对逻辑 i 进行回收,因为它隐藏了比难得的便利更多的错误。如果确实需要回收,请显式使用 rep(...,length=.N)。
  • 首先它必须转换为data.frame()。现在我在我的手机里。我会简短地编辑。
【解决方案2】:

您仍然可以使用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)]

【讨论】:

  • @Seni 很高兴有帮助。您可以考虑通过单击投票按钮旁边的复选标记来接受答案。你可以阅读更多关于它的信息here
【解决方案3】:

如果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)

【讨论】:

  • 谢谢,但它返回 - 错误:列 ChrV 未知
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-03
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
  • 2019-05-08
  • 1970-01-01
相关资源
最近更新 更多