计算 R 中数据框中每一行的前导和尾随零
counting leading & trailing zeros for every row in a dataframe in R
我正在尝试分析一个数据框,其中每一行都代表一个时间序列。我的 df 结构如下:
df <- data.frame(key = c("10A", "11xy", "445pe"),
Obs1 = c(0, 22, 0),
Obs2 = c(10, 0, 0),
Obs3 = c(0, 3, 5),
Obs4 = c(0, 10, 0)
)
我现在想创建一个新的数据框,其中每一行再次代表键,列由以下结果组成:
- “TotalZeros”:计算每行零的总数(=key)
- “LeadingZeros”:计算每行第一个非零 obs 之前的零数
这意味着我想最终收到以下数据帧:
key TotalZeros LeadingZeros
10A 3 1
11xy 1 0
445pe 3 2
我设法计算了每行零的总数:
zeroCountDf <- data.frame(key = df$key, TotalNonZeros = rowSums(df ! = 0))
但我正在努力数 LeadingZeros
。我找到了如何计算向量中的第一个非零位置,但我不明白如何将这种方法应用于我的数据框:
vec <- c(0,1,1)
min(which(vec != 0)) # returns 2, meaning the second position is first nonzero value
谁能解释如何计算数据框中每一行的前导零?我是 R 的新手,感谢任何见解和提示。提前致谢。
编辑 将 Miff 的评论添加到解决方案中。
这是一个tidyverse
解决方案:
library(dplyr)
library(tidyr)
df %>%
pivot_longer(starts_with("Obs"),
names_pattern = "Obs(\d+)") %>%
arrange(key, as.integer(name)) %>%
group_by(key) %>%
summarize(
leading_zeros = sum(cumsum(abs(value)) == 0),
total_zeros = sum(value == 0),
trailing_zeros = sum(cumsum(abs(value)) == last(cumsum(abs(value)))) - 1)
这个returns
# A tibble: 3 x 4
key leading_zeros total_zeros trailing_zeros
<chr> <int> <int> <dbl>
1 10A 1 3 2
2 11xy 0 1 0
3 445pe 2 3 1
我们可以使用 matrixStats
中的 rowCumsums
以及 rowSums
library(matrixStats)
cbind(df[1], total_zeros = rowSums(df[-1] == 0),
Leading_zeros = rowSums(!rowCumsums(df[-1] != 0)))
-输出
key total_zeros Leading_zeros
1 10A 3 1
2 11xy 1 0
3 445pe 3 2
或者在tidyverse中,我们也可以使用rowwise
library(dplyr)
df %>%
mutate(total_zeros = rowSums(select(., starts_with("Obs")) == 0)) %>%
rowwise %>%
transmute(key, total_zeros,
Leading_zeros = sum(!cumsum(c_across(starts_with('Obs')) != 0))) %>%
ungroup
-输出
# A tibble: 3 x 3
key total_zeros Leading_zeros
<chr> <dbl> <int>
1 10A 3 1
2 11xy 1 0
3 445pe 3 2
一个data.table
选项
setDT(df)[
, .(
total_zeros = rowSums(.SD == 0),
Leading_zeros = which.max(.SD != 0) - 1,
Trailing_zeros = length(.SD)-max(which(.SD!=0))
),
key
]
给予
key total_zeros Leading_zeros Trailing_zeros
1: 10A 3 1 2
2: 11xy 1 0 0
3: 445pe 3 2 1
我正在尝试分析一个数据框,其中每一行都代表一个时间序列。我的 df 结构如下:
df <- data.frame(key = c("10A", "11xy", "445pe"),
Obs1 = c(0, 22, 0),
Obs2 = c(10, 0, 0),
Obs3 = c(0, 3, 5),
Obs4 = c(0, 10, 0)
)
我现在想创建一个新的数据框,其中每一行再次代表键,列由以下结果组成:
- “TotalZeros”:计算每行零的总数(=key)
- “LeadingZeros”:计算每行第一个非零 obs 之前的零数
这意味着我想最终收到以下数据帧:
key TotalZeros LeadingZeros
10A 3 1
11xy 1 0
445pe 3 2
我设法计算了每行零的总数:
zeroCountDf <- data.frame(key = df$key, TotalNonZeros = rowSums(df ! = 0))
但我正在努力数 LeadingZeros
。我找到了如何计算向量中的第一个非零位置,但我不明白如何将这种方法应用于我的数据框:
vec <- c(0,1,1)
min(which(vec != 0)) # returns 2, meaning the second position is first nonzero value
谁能解释如何计算数据框中每一行的前导零?我是 R 的新手,感谢任何见解和提示。提前致谢。
编辑 将 Miff 的评论添加到解决方案中。
这是一个tidyverse
解决方案:
library(dplyr)
library(tidyr)
df %>%
pivot_longer(starts_with("Obs"),
names_pattern = "Obs(\d+)") %>%
arrange(key, as.integer(name)) %>%
group_by(key) %>%
summarize(
leading_zeros = sum(cumsum(abs(value)) == 0),
total_zeros = sum(value == 0),
trailing_zeros = sum(cumsum(abs(value)) == last(cumsum(abs(value)))) - 1)
这个returns
# A tibble: 3 x 4
key leading_zeros total_zeros trailing_zeros
<chr> <int> <int> <dbl>
1 10A 1 3 2
2 11xy 0 1 0
3 445pe 2 3 1
我们可以使用 matrixStats
中的 rowCumsums
以及 rowSums
library(matrixStats)
cbind(df[1], total_zeros = rowSums(df[-1] == 0),
Leading_zeros = rowSums(!rowCumsums(df[-1] != 0)))
-输出
key total_zeros Leading_zeros
1 10A 3 1
2 11xy 1 0
3 445pe 3 2
或者在tidyverse中,我们也可以使用rowwise
library(dplyr)
df %>%
mutate(total_zeros = rowSums(select(., starts_with("Obs")) == 0)) %>%
rowwise %>%
transmute(key, total_zeros,
Leading_zeros = sum(!cumsum(c_across(starts_with('Obs')) != 0))) %>%
ungroup
-输出
# A tibble: 3 x 3
key total_zeros Leading_zeros
<chr> <dbl> <int>
1 10A 3 1
2 11xy 1 0
3 445pe 3 2
一个data.table
选项
setDT(df)[
, .(
total_zeros = rowSums(.SD == 0),
Leading_zeros = which.max(.SD != 0) - 1,
Trailing_zeros = length(.SD)-max(which(.SD!=0))
),
key
]
给予
key total_zeros Leading_zeros Trailing_zeros
1: 10A 3 1 2
2: 11xy 1 0 0
3: 445pe 3 2 1