【问题标题】:How to make bin for the each row of dataframe only with the non NA values?如何仅使用非 NA 值为每一行数据帧制作 bin?
【发布时间】:2025-12-07 15:10:03
【问题描述】:

我有一个包含值和 NA 的数据框。其中一些具有行首的 NA,其中一些具有行尾的 NA。

# like this way
df<- data.frame(A=c(1,5,6,   1,NA,NA),
                  B=c(1,2,3,   2,NA,NA),
                  C=c(1,3,NA,  4,3,NA),
                  D=c(1,1,NA,  6,10,NA),
                  E=c(1,NA,NA, 1,1,1),
                  F=c(1,NA,NA, 1,1,1))

现在我想根据非 NA 值为每一行构建两个 bin 并将它们相加。

#expected output
Sum   Bin
3     1
3     2
7     1
5     2
6     1
3     2
...

现在我所做的是我首先根据行是以 NA 开头还是结尾将数据框分成 2 个。然后我使用循环进行计算。

df_bin <- data.frame(Sum = 0, Bin = 0)

bin  = 2 # set bin for the calculation
for (i in 1:nrow(df)) {
  l <- sum(!is.na(df[i,]))
  ll <- as.integer(l/bin)
  s <- c()
  j <- 1
  while (j <= (bin-1)) {
    k <- sum(df[i,(j*ll-ll+1):(j*ll)])
    s <- c(s,k) 
    j = j+1
  }
  k <- k <- sum(df[i,(j*(bin-1)+1):l])
  s <- c(s,k) 
  df2 <- data.frame(Sum = s, Bin = 1:bin)
  df_bin <- rbind(df_bin,df2)
}

但是它运行得很慢,我想知道是否有更优雅的方式来做到这一点。提前谢谢你:)

【问题讨论】:

  • 我对你如何计算你想要的输出感到困惑......你能解释一下SumBin 的计算是如何完成的(按行)?
  • @Wimpel 是的,我为每一行计算 Bin 中的列总和

标签: r dataframe dplyr apply


【解决方案1】:

使用旋转的纯tidyverse 解决方案:

df %>%
  mutate(orig_row = 1:n()) %>%
  pivot_longer(-orig_row) %>% filter(!is.na(value)) %>%
  group_by(orig_row) %>% mutate(Bin = round(1 + seq(0, n() - 1) / n())) %>%
  group_by(orig_row, Bin) %>% summarise(Sum = sum(value)) %>% ungroup() %>%
  select(-orig_row)

结果:

# A tibble: 12 x 2
     Bin   Sum
   <dbl> <dbl>
 1     1     3
 2     2     3
 3     1     7
 4     2     4
 5     1     6
 6     2     3
 7     1     7
 8     2     8
 9     1    13
10     2     2
11     1     1
12     2     1

【讨论】:

  • 你好,我想知道我是否想通过使用 100 个 bin 来对值求和。现在我使用 %>% mutate(Bin = round(1 + seq(0, n() - 1) / n()*99))。但它使某些行丢失了最后一个 bin(bin 100)。你有什么建议吗?
  • 对不起,我之前并没有真正考虑过如何推广到更多的垃圾箱。在这种情况下,我会使用mutate(Bin = ceiling(2 * seq_along(value) / n())),将2 替换为您需要的垃圾箱数量。让我知道这是否适合您
【解决方案2】:

您可以尝试使用apply

do.call(rbind, apply(df, 1, function(x) {
  #Remove NA values
  x1 <- na.omit(x)
  #Calculate length of non-NA values
  n <- length(x1)
  #Calculate mid point
  half_len <- round(n/2)
  #Create dataframe with sum of two bin values
  data.frame(Sum = c(sum(x1[1:half_len]), sum(x1[(half_len + 1):n])), 
             Bin = 1:2)
}))

#   Sum Bin
#1    3   1
#2    3   2
#3    7   1
#4    4   2
#5    6   1
#6    3   2
#7    7   1
#8    8   2
#9   13   1
#10   2   2
#11   1   1
#12   1   2

【讨论】:

    最近更新 更多