按 R 中的等级和条件提取行

Extract rows by rank and condition in R

我试图了解如何根据一个数字列中的值从 table 中提取前十行,但只能从满足应用于第二个数字列的条件的行中提取。
先说数据。我有一个 table 列表,其中包含几千个人类基因、与对照的表达差异 (log_fold_change) 以及该差异的 p 值 (p_value)。 table 看起来像这样:

       log_fold_change   p_value
APOD         1.7388209 0.4820801
S100B       -1.1514299 0.5995658
CD63         0.6066951 0.4935413
PMEL        -1.4977796 0.1862176
MT2A        -0.9311173 0.8273733
S100A6      -0.4555436 0.6684667
TIMP1       -1.9464387 0.7942399
VIM         -0.4704482 0.1079436
PAEP         1.4787634 0.7237109
CSTB        -0.6386040 0.4112744

可以使用这些命令重新创建数据(使用 n 虚构基因的数据创建 table):

n <- 50    
log_fold_change <- runif(n, -2.0, 2.0)
p_value <- runif(n, 0, 1.0)  
df <- data.frame(log_fold_change, p_value)
rownames(df) <- stringi::stri_paste(stringi::stri_rand_strings(n, 3, '[A-Z]'),stringi::stri_rand_strings(n, 1, '[1-9]'))

我已经为标签创建了一个列 (df$label <- NA),我计划在其中传输我在绘制图形时要标记的基因名称。你问哪些基因?我希望在 log_fold_change 为正的基因中,提取出 p_value 最小的十个基因。
我已经找到了提取和标记最小的10个基因的方法p_value:

df$label[with(df, rank(p_value)) %in% c(1:10)] <- rownames(df)[with(df, rank(p_value)) %in% c(1:10)]

现在,我如何执行条件 df$log_fold_change > 0,以便我的十个具有最小 p_value 的基因仅从具有正 log_fold_change 的基因中选出?任何帮助将不胜感激!

dplyr解法:

library(dplyr)

df %>%
  filter(log_fold_change > 0) %>%
  arrange(p_value) %>%
  head(10) %>%
  mutate(labels = rownames(.))

输出:

      A data.frame: 10 × 3
log_fold_change p_value label
   <dbl>       <dbl>    <chr>
0.9672121   0.01423086  MBT4
1.7139128   0.05044393  INQ3
0.4809652   0.10347463  ORW1
0.2949034   0.13493936  FVR2
0.9967781   0.17676960  JHP1
1.0813577   0.23599439  ITE9
1.0670343   0.25001069  ANQ4
1.5954271   0.26273176  XVL8
1.8803123   0.30065841  IQV6
0.3591054   0.46889062  JLD9

首先,您用 filter(log_fold_change > 0) 丢弃 log_fold_change 列中小于或等于 0 的所有观察值。然后按 arrange(p_value) 和 select 的升序排列 p_value 列,前 10 个观察值 head(10)。最后使用 mutate() 创建带有基因名称的 label 列。这为您提供了 10 个具有最低 p_value 的观察值,其中 log_fold_change 为正值。

使用 base R 可以这样实现:

  1. 将你的 df 拆分 log_fold_change > 0
  2. 为每个拆分分别设置标签
  3. 重新绑定在一起
n <- 50    
log_fold_change <- runif(n, -2.0, 2.0)
p_value <- runif(n, 0, 1.0)  
df <- data.frame(log_fold_change, p_value)
rownames(df) <- stringi::stri_paste(stringi::stri_rand_strings(n, 3, '[A-Z]'),stringi::stri_rand_strings(n, 1, '[1-9]'))

df_split <- split(df, df$log_fold_change > 0) 
df_split[["FALSE"]]$label <- NA
df_split[["TRUE"]]$label <- with(df_split[["TRUE"]], rank(-p_value))
df_split[["TRUE"]]$label <- ifelse(df_split[["TRUE"]]$label %in% 1:10, row.names(df_split[["TRUE"]]), NA)
df <- rbind(df_split[["FALSE"]], df_split[["TRUE"]])

df[!is.na(df$label),]
#>      log_fold_change   p_value label
#> IPQ1      1.46479105 0.9928132  IPQ1
#> GDA3      0.26974526 0.9696272  GDA3
#> CHU3      0.31643010 0.7094205  CHU3
#> IDE1      0.87836008 0.7152144  IDE1
#> KQJ9      1.12647503 0.7854047  KQJ9
#> FQM8      1.99924827 0.8463336  FQM8
#> RPO1      0.10874876 0.7279679  RPO1
#> TOA9      1.88312825 0.7143039  TOA9
#> EXG7      1.82497903 0.8082063  EXG7
#> RGE9      0.02894958 0.7685504  RGE9

reprex package (v0.3.0)

于 2020-10-03 创建

您可以先对数据进行排序,获取 log_fold_change > 0 中的 10 个值并将行名传输到 label 列。

df <- df[order(df$log_fold_change), ]
inds <- which(df$log_fold_change > 0)[1:10]
df$label[inds] <- rownames(df)[inds]

这将使您的原始 df 保持原样,您将只在这 10 行中有 label

如果您只想要那 10 行,您可以这样做:

df1 <- df[inds, ]