【问题标题】:Calculate Z-Score for every N rows in a DF (R)计算 DF (R) 中每 N 行的 Z 分数
【发布时间】:2020-07-23 08:41:58
【问题描述】:

您好,我有一个 df,其中包含变量,因为列和行是时间。每个交叉点的元素是一个计数。

      Var_1 Var_2 Var_3 
Time_1 5     4      5
Time_2 4     19     4 
Time_3 2     2     87

这个df有很多行(> 30,000)

如何计算每 20 行的 Z 分数?提前致谢!

【问题讨论】:

  • 请分享足够的数据来演示解决方案。可能总共有 6 行,所以我们可以展示每 3 行的 z 分数?还请具体说明您希望如何处理列 - 您是否想要每 20 行每列的 z 分数?还是您希望以某种方式组合列?而且,您是否想要 20 行块,例如 1:20、21:40、41:60 等行?或者你想要一个滚动窗口,行 1:20、2:21、3:22?

标签: r loops dataframe statistics


【解决方案1】:

这是一个使用dplyr::summarise() 计算均值和标准差的答案,然后我们将它们与原始数据合并并使用mutate() 计算z 分数。我们将举例说明单变量的情况,但它可以扩展到处理多个变量。

鉴于原始问题的模棱两可,我们假设Time- 列以 20 个为一组构成,这允许我们将其用作解决方案的主要分组变量。也就是说,Time-1 有 20 个观测值,Time-2 有另外 20 个观测值,等等。

如果要求基于连续行标识符创建 20 行的组,则可以轻松修改解决方案以添加分组变量来表示 20 行的集合。

# simulate some data
y <- rpois(20000,3) # simulate counts 
TimeVal <- paste0(rep("Time-",20000),
                  rep(1:1000,20))

data <-data.frame(TimeVal,y,stringsAsFactors = FALSE)
library(dplyr)
result <- data %>% group_by(TimeVal) %>% summarise(ybar = mean(y),
                                                        stDev = sd(y)) %>%
               full_join(data,.,) %>% mutate(.,zScore = (y - ybar) / stDev)
head(result)

...和输出:

> head(result)
  TimeVal y ybar    stDev      zScore
1  Time-1 6 3.45 1.276302  1.99795938
2  Time-2 2 2.95 1.700619 -0.55862010
3  Time-3 2 3.20 1.908430 -0.62878909
4  Time-4 3 3.10 1.916686 -0.05217339
5  Time-5 2 3.10 1.447321 -0.76002513
6  Time-6 2 3.30 1.809333 -0.71849700
> 

扩展解决方案:多列的 z-scores

为了解决原始输入数据框中的多列问题,首先我们使用tidyr::pivot_longer) 创建一个长格式的整洁数据框,计算均值和标准差,将它们与窄数据合并并计算z-scores。

将输入数据转换为长格式整洁的数据框允许我们使用dplyr::by_group() 中的原始列名,从而消除了计算原始中每一列的 z 分数所需的大量代码数据。

library(tidyr)
set.seed(95014) # set seed to make results reproducible 
y2 <- rpois(20000,8)
y3 <- rpois(20000,15)    
data <- data.frame(TimeVal,y,y2,y3,stringsAsFactors = FALSE)

# convert to narrow format tidy, calculate means, sds, and zScores
longData <- data %>% 
  group_by(TimeVal) %>%
  pivot_longer(-TimeVal, 
      names_to = "variable",                                                         
      values_to = "value")  
result <- longData %>% 
  group_by(TimeVal,variable) %>% 
  summarise(avg = mean(value), stDev = sd(value)) %>%
  full_join(longData,.) %>% 
  mutate(.,zScore = (value - avg) / stDev)
head(result)

...和输出:

> head(result)
# A tibble: 6 x 6
# Groups:   TimeVal [2]
  TimeVal variable value   avg stDev zScore
  <chr>   <chr>    <int> <dbl> <dbl>  <dbl>
1 Time-1  y            6  3.45  1.28  2.00 
2 Time-1  y2          13  8.7   2.23  1.93 
3 Time-1  y3          20 16.4   5.25  0.686
4 Time-2  y            2  2.95  1.70 -0.559
5 Time-2  y2           6  8.2   2.89 -0.760
6 Time-2  y3          12 14.8   3.34 -0.852
> 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-14
    相关资源
    最近更新 更多