如何选择在特定分位数范围内的观测值

4

我有这样的数据(约1000行):

head(data)

   alt   alb   alp alt_zscore alb_zscore alp_zscore
 <dbl> <dbl> <dbl>      <dbl>      <dbl>      <dbl>
1  11    2.60   9       -1.54      -7.82      -0.949
2  12    5.37  86.3     -1.45      -0.351      2.31 
3  15.7  4.67  28       -1.09      -2.24      -0.148
4   7    4.43 171.      -1.93      -2.89       5.87 
5  14.5  3.75  12       -1.20      -4.72      -0.822
6  17.5  3.70  82.5     -0.915     -4.86       2.15

每个变量列(即altalbalp)都有一个相应的z分数列(alt_zscorealb_zscorealp_zscore)。
在我的之前的代码中,我告诉R,对于每个z分数列,如果观察值比平均值低1个标准差以上,就取z分数观察值的绝对值;如果不符合条件,则给它赋值为0。(我这样做的原因是因为在我的代码后面,我将所有这些z分数观察值相加到另一列中。)
以下是我的之前的代码:
name <- c("alt_zscore", "alb_zscore", "alp_zscore")

stdev <- 1

lf <- list(
  \(x) ifelse(x <= -stdev, abs(x), 0),
  \(x) ifelse(x <= -stdev, abs(x), 0),
  \(x) ifelse(x <= -stdev, abs(x), 0)
) %>% 
  setNames(name)

我这样做的原因是为了创建一个名为“total_score”的新列,该列是符合我的条件的所有z分数的总和。
data <- data %>% 
  mutate(total_score = rowSums(across(all_of(name), ~ lf[[cur_column()]](.)), na.rm = TRUE))

现在,我要做的是告诉R,对于每个“常规”列(即,在这里我指的是'alt'而不是'alt_zscore'),如果一个观察值小于该列的第25百分位数,那么取其对应的z得分列(alt_zscore)的绝对值;否则,将其设为零。注意:有时我需要指定第75百分位数,或者第25或第75百分位数,所以希望代码在这方面是可调整的。
我正在尝试修改我的现有代码来实现这一点,但没有成功。任何帮助将不胜感激。谢谢!
1个回答

4
您可以使用 across() 结合 cur_column() 来搜索相应的 z-分数列。
library(dplyr)

df %>%
  mutate(across(alt:alp,
                ~ if_else(.x < quantile(.x, .25), abs(get(paste0(cur_column(), "_zscore"))), 0),
                .names = "{.col}_new"))

#    alt  alb   alp alt_zscore alb_zscore alp_zscore alt_new alb_new alp_new
# 1 11.0 2.60   9.0     -1.540     -7.820     -0.949    1.54    7.82   0.949
# 2 12.0 5.37  86.3     -1.450     -0.351      2.310    0.00    0.00   0.000
# 3 15.7 4.67  28.0     -1.090     -2.240     -0.148    0.00    0.00   0.000
# 4  7.0 4.43 171.0     -1.930     -2.890      5.870    1.93    0.00   0.000
# 5 14.5 3.75  12.0     -1.200     -4.720     -0.822    0.00    0.00   0.822
# 6 17.5 3.70  82.5     -0.915     -4.860      2.150    0.00    4.86   0.000

对于你的第一个任务,函数列表(lf)是不需要的,因为所有的函数都是相同的。
df %>% 
  mutate(total_score = rowSums(
    across(alt_zscore:alp_zscore, ~ ifelse(.x <= -1, abs(.x), 0)), na.rm = TRUE
  ))

数据
df <- read.table(text =
"   alt   alb   alp alt_zscore alb_zscore alp_zscore
1  11    2.60   9       -1.54      -7.82      -0.949
2  12    5.37  86.3     -1.45      -0.351      2.31 
3  15.7  4.67  28       -1.09      -2.24      -0.148
4   7    4.43 171.      -1.93      -2.89       5.87 
5  14.5  3.75  12       -1.20      -4.72      -0.822
6  17.5  3.70  82.5     -0.915     -4.86       2.15")

1
很好的回答!我也曾经想过这个问题。 - stats_noob
如果altalbalp的标准是相同的,你可以在across()内部修改if_else()部分。例如:~ if_else(.x < quantile(.x, .25) | .x > quantile(.x, .75), abs(get(paste0(cur_column(), "_zscore"))), 0) - Darren Tsai
@DarrenTsai 謝謝你的關心!我目前正在處理這個問題,但我預計問題會解決。為了保持簡單(也許我應該這樣做),我在我的範例 df 中沒有提供其他列,但是除了 alt、alb、alp 等我不會在這些計算中使用其他列,所以我可能需要為每個要使用的列使用一個單獨的 mutate 參數,而不是使用 across 函數。再次感謝你的幫助! - burphound
@DarrenTsai 我的意思是,为什么选择 x<-1?对于代码的这部分,我想要将所有的“_zscore”值相加。 - burphound
@burphound 哦,那是个打字错误!我已经修正了。应该是 across(alt_zscore:alp_zscore, ...) 而不是 across(alt:alp, ...) - Darren Tsai
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接