Rank groups within a grouped sequence of TRUE/FALSE and NA The 2019 Stack Overflow Developer Survey Results Are InGrouping functions (tapply, by, aggregate) and the *apply familyCharacters counting and subletting specific patternsdata.table vs dplyr: can one do something well the other can't or does poorly?how to make a bar plot for a list of dataframes?How to group by unique values in a list in RUsing Group by in R using dplyrPandas - Alternative to rank() function that gives unique ordinal ranks for a columnRank within group in for loop in RFilter two tables with crosstalkGetting map from purrr to work with paste0
I see my dog run
Could a US political party gain complete control over the government by removing checks & balances?
Why do some words that are not inflected have an umlaut?
What is the steepest angle that a canal can be traversable without locks?
Are there any other methods to apply to solving simultaneous equations?
Unbreakable Formation vs. Cry of the Carnarium
Understanding the implication of what "well-defined" means for the operation in quotient group
How can I make payments on the Internet without leaving a money trail?
Is bread bad for ducks?
What does "sndry explns" mean in one of the Hitchhiker's guide books?
Realistic Alternatives to Dust: What Else Could Feed a Plankton Bloom?
How can I fix this gap between bookcases I made?
Rank groups within a grouped sequence of TRUE/FALSE and NA
What are the motivations for publishing new editions of an existing textbook, beyond new discoveries in a field?
How to manage monthly salary
What could be the right powersource for 15 seconds lifespan disposable giant chainsaw?
How are circuits which use complex ICs normally simulated?
Should I use my personal or workplace e-mail when registering to external websites for work purpose?
When to use the root test. Is this not a good situation to use it?
How come people say “Would of”?
Inflated grade on resume at previous job, might former employer tell new employer?
Why is Grand Jury testimony secret?
Does a dangling wire really electrocute me if I'm standing in water?
A poker game description that does not feel gimmicky
Rank groups within a grouped sequence of TRUE/FALSE and NA
The 2019 Stack Overflow Developer Survey Results Are InGrouping functions (tapply, by, aggregate) and the *apply familyCharacters counting and subletting specific patternsdata.table vs dplyr: can one do something well the other can't or does poorly?how to make a bar plot for a list of dataframes?How to group by unique values in a list in RUsing Group by in R using dplyrPandas - Alternative to rank() function that gives unique ordinal ranks for a columnRank within group in for loop in RFilter two tables with crosstalkGetting map from purrr to work with paste0
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
I have a little nut to crack.
I have a data.frame
like this:
group criterium
1 A NA
2 A TRUE
3 A TRUE
4 A TRUE
5 A FALSE
6 A FALSE
7 A TRUE
8 A TRUE
9 A FALSE
10 A TRUE
11 A TRUE
12 A TRUE
13 B NA
14 B FALSE
15 B TRUE
16 B TRUE
17 B TRUE
18 B FALSE
structure(list(group = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("A",
"B"), class = "factor"), criterium = c(NA, TRUE, TRUE, TRUE,
FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, NA, FALSE,
TRUE, TRUE, TRUE, FALSE)), class = "data.frame", row.names = c(NA,
-18L))
And I want to rank the groups of TRUE
in column criterium
in ascending order while disregarding the FALSE
and NA
. The goal is to have a unique group identifier inside each group of group
.
So the result should look like:
group criterium goal
1 A NA NA
2 A TRUE 1
3 A TRUE 1
4 A TRUE 1
5 A FALSE NA
6 A FALSE NA
7 A TRUE 2
8 A TRUE 2
9 A FALSE NA
10 A TRUE 3
11 A TRUE 3
12 A TRUE 3
13 B NA NA
14 B FALSE NA
15 B TRUE 1
16 B TRUE 1
17 B TRUE 1
18 B FALSE NA
I'm sure there is a relatively easy way to do this, I just can't think of one. I experimented with dense_rank()
and other window functions of dplyr
, but to no avail.
Thanks for the help!
r dplyr rank
add a comment |
I have a little nut to crack.
I have a data.frame
like this:
group criterium
1 A NA
2 A TRUE
3 A TRUE
4 A TRUE
5 A FALSE
6 A FALSE
7 A TRUE
8 A TRUE
9 A FALSE
10 A TRUE
11 A TRUE
12 A TRUE
13 B NA
14 B FALSE
15 B TRUE
16 B TRUE
17 B TRUE
18 B FALSE
structure(list(group = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("A",
"B"), class = "factor"), criterium = c(NA, TRUE, TRUE, TRUE,
FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, NA, FALSE,
TRUE, TRUE, TRUE, FALSE)), class = "data.frame", row.names = c(NA,
-18L))
And I want to rank the groups of TRUE
in column criterium
in ascending order while disregarding the FALSE
and NA
. The goal is to have a unique group identifier inside each group of group
.
So the result should look like:
group criterium goal
1 A NA NA
2 A TRUE 1
3 A TRUE 1
4 A TRUE 1
5 A FALSE NA
6 A FALSE NA
7 A TRUE 2
8 A TRUE 2
9 A FALSE NA
10 A TRUE 3
11 A TRUE 3
12 A TRUE 3
13 B NA NA
14 B FALSE NA
15 B TRUE 1
16 B TRUE 1
17 B TRUE 1
18 B FALSE NA
I'm sure there is a relatively easy way to do this, I just can't think of one. I experimented with dense_rank()
and other window functions of dplyr
, but to no avail.
Thanks for the help!
r dplyr rank
add a comment |
I have a little nut to crack.
I have a data.frame
like this:
group criterium
1 A NA
2 A TRUE
3 A TRUE
4 A TRUE
5 A FALSE
6 A FALSE
7 A TRUE
8 A TRUE
9 A FALSE
10 A TRUE
11 A TRUE
12 A TRUE
13 B NA
14 B FALSE
15 B TRUE
16 B TRUE
17 B TRUE
18 B FALSE
structure(list(group = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("A",
"B"), class = "factor"), criterium = c(NA, TRUE, TRUE, TRUE,
FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, NA, FALSE,
TRUE, TRUE, TRUE, FALSE)), class = "data.frame", row.names = c(NA,
-18L))
And I want to rank the groups of TRUE
in column criterium
in ascending order while disregarding the FALSE
and NA
. The goal is to have a unique group identifier inside each group of group
.
So the result should look like:
group criterium goal
1 A NA NA
2 A TRUE 1
3 A TRUE 1
4 A TRUE 1
5 A FALSE NA
6 A FALSE NA
7 A TRUE 2
8 A TRUE 2
9 A FALSE NA
10 A TRUE 3
11 A TRUE 3
12 A TRUE 3
13 B NA NA
14 B FALSE NA
15 B TRUE 1
16 B TRUE 1
17 B TRUE 1
18 B FALSE NA
I'm sure there is a relatively easy way to do this, I just can't think of one. I experimented with dense_rank()
and other window functions of dplyr
, but to no avail.
Thanks for the help!
r dplyr rank
I have a little nut to crack.
I have a data.frame
like this:
group criterium
1 A NA
2 A TRUE
3 A TRUE
4 A TRUE
5 A FALSE
6 A FALSE
7 A TRUE
8 A TRUE
9 A FALSE
10 A TRUE
11 A TRUE
12 A TRUE
13 B NA
14 B FALSE
15 B TRUE
16 B TRUE
17 B TRUE
18 B FALSE
structure(list(group = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("A",
"B"), class = "factor"), criterium = c(NA, TRUE, TRUE, TRUE,
FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, NA, FALSE,
TRUE, TRUE, TRUE, FALSE)), class = "data.frame", row.names = c(NA,
-18L))
And I want to rank the groups of TRUE
in column criterium
in ascending order while disregarding the FALSE
and NA
. The goal is to have a unique group identifier inside each group of group
.
So the result should look like:
group criterium goal
1 A NA NA
2 A TRUE 1
3 A TRUE 1
4 A TRUE 1
5 A FALSE NA
6 A FALSE NA
7 A TRUE 2
8 A TRUE 2
9 A FALSE NA
10 A TRUE 3
11 A TRUE 3
12 A TRUE 3
13 B NA NA
14 B FALSE NA
15 B TRUE 1
16 B TRUE 1
17 B TRUE 1
18 B FALSE NA
I'm sure there is a relatively easy way to do this, I just can't think of one. I experimented with dense_rank()
and other window functions of dplyr
, but to no avail.
Thanks for the help!
r dplyr rank
r dplyr rank
edited 56 mins ago
Humpelstielzchen
asked 1 hour ago
HumpelstielzchenHumpelstielzchen
1,3401316
1,3401316
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
Maybe I have over-complicated this but one way with dplyr
is
library(dplyr)
df %>%
mutate(temp = replace(criterium, is.na(criterium), FALSE),
temp1 = cumsum(!temp)) %>%
group_by(temp1) %>%
mutate(goal = +(row_number() == which.max(temp) & any(temp))) %>%
group_by(group) %>%
mutate(goal = ifelse(temp, cumsum(goal), NA)) %>%
select(-temp, -temp1)
# group criterium goal
# <fct> <lgl> <int>
# 1 A NA NA
# 2 A TRUE 1
# 3 A TRUE 1
# 4 A TRUE 1
# 5 A FALSE NA
# 6 A FALSE NA
# 7 A TRUE 2
# 8 A TRUE 2
# 9 A FALSE NA
#10 A TRUE 3
#11 A TRUE 3
#12 A TRUE 3
#13 B NA NA
#14 B FALSE NA
#15 B TRUE 1
#16 B TRUE 1
#17 B TRUE 1
#18 B FALSE NA
We first replace
NA
s in criterium
column to FALSE
and take cumulative sum over the negation of it (temp1
). We group_by
temp1
and assign 1 to every first TRUE
value in the group. Finally grouping by group
we take a cumulative sum for TRUE
values or return NA
for FALSE
and NA
values.
add a comment |
We can create a custom function via rle
, and use it per group, i.e.
f1 <- function(x)
x[is.na(x)] <- FALSE
rle1 <- rle(x)
y <- rle1$values
rle1$values[!y] <- 0
rle1$values[y] <- cumsum(rle1$values[y])
return(inverse.rle(rle1))
do.call(rbind,
lapply(split(df, df$group), function(i)!i$criterium, NA);
i))
Of course, If you want you can apply it via dplyr
, i.e.
library(dplyr)
df %>%
group_by(group) %>%
mutate(goal = f1(criterium),
goal = replace(goal, is.na(criterium)|!criterium, NA))
which gives,
# A tibble: 18 x 3
# Groups: group [2]
group criterium goal
<fct> <lgl> <dbl>
1 A NA NA
2 A TRUE 1
3 A TRUE 1
4 A TRUE 1
5 A FALSE NA
6 A FALSE NA
7 A TRUE 2
8 A TRUE 2
9 A FALSE NA
10 A TRUE 3
11 A TRUE 3
12 A TRUE 3
13 B NA NA
14 B FALSE NA
15 B TRUE 1
16 B TRUE 1
17 B TRUE 1
18 B FALSE NA
add a comment |
A different dplyr
possibility using rle()
and dense_rank()
could be:
df %>%
group_by(group) %>%
mutate(rleid = with(rle(criterium), rep(seq_along(lengths), lengths))) %>%
group_by(group, criterium) %>%
mutate(res = dense_rank(rleid)) %>%
ungroup() %>%
mutate(res = ifelse(criterium, res, NA)) %>%
select(-rleid)
group criterium res
<fct> <lgl> <int>
1 A NA NA
2 A TRUE 1
3 A TRUE 1
4 A TRUE 1
5 A FALSE NA
6 A FALSE NA
7 A TRUE 2
8 A TRUE 2
9 A FALSE NA
10 A TRUE 3
11 A TRUE 3
12 A TRUE 3
13 B NA NA
14 B FALSE NA
15 B TRUE 1
16 B TRUE 1
17 B TRUE 1
18 B FALSE NA
add a comment |
A data.table
option using rle
library(data.table)
DT <- as.data.table(dat)
DT[, goal :=
r <- rle(replace(criterium, is.na(criterium), FALSE))
r$values <- with(r, cumsum(values) * values)
out <- inverse.rle(r)
replace(out, out == 0, NA)
, by = group]
DT
# group criterium goal
# 1: A NA NA
# 2: A TRUE 1
# 3: A TRUE 1
# 4: A TRUE 1
# 5: A FALSE NA
# 6: A FALSE NA
# 7: A TRUE 2
# 8: A TRUE 2
# 9: A FALSE NA
#10: A TRUE 3
#11: A TRUE 3
#12: A TRUE 3
#13: B NA NA
#14: B FALSE NA
#15: B TRUE 1
#16: B TRUE 1
#17: B TRUE 1
#18: B FALSE NA
data
dat <- structure(list(group = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("A",
"B"), class = "factor"), criterium = c(NA, TRUE, TRUE, TRUE,
FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, NA, FALSE,
TRUE, TRUE, TRUE, FALSE)), class = "data.frame", row.names = c(NA,
-18L))
Wow, impressive. Thanks for introducing me torle
andinverse.rle
. Gruß nach Leipzig.
– Humpelstielzchen
20 mins ago
@Humpelstielzchen Gern geschehen. Will try to simplify and explain the logic a bit.
– markus
16 mins ago
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55606323%2frank-groups-within-a-grouped-sequence-of-true-false-and-na%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
Maybe I have over-complicated this but one way with dplyr
is
library(dplyr)
df %>%
mutate(temp = replace(criterium, is.na(criterium), FALSE),
temp1 = cumsum(!temp)) %>%
group_by(temp1) %>%
mutate(goal = +(row_number() == which.max(temp) & any(temp))) %>%
group_by(group) %>%
mutate(goal = ifelse(temp, cumsum(goal), NA)) %>%
select(-temp, -temp1)
# group criterium goal
# <fct> <lgl> <int>
# 1 A NA NA
# 2 A TRUE 1
# 3 A TRUE 1
# 4 A TRUE 1
# 5 A FALSE NA
# 6 A FALSE NA
# 7 A TRUE 2
# 8 A TRUE 2
# 9 A FALSE NA
#10 A TRUE 3
#11 A TRUE 3
#12 A TRUE 3
#13 B NA NA
#14 B FALSE NA
#15 B TRUE 1
#16 B TRUE 1
#17 B TRUE 1
#18 B FALSE NA
We first replace
NA
s in criterium
column to FALSE
and take cumulative sum over the negation of it (temp1
). We group_by
temp1
and assign 1 to every first TRUE
value in the group. Finally grouping by group
we take a cumulative sum for TRUE
values or return NA
for FALSE
and NA
values.
add a comment |
Maybe I have over-complicated this but one way with dplyr
is
library(dplyr)
df %>%
mutate(temp = replace(criterium, is.na(criterium), FALSE),
temp1 = cumsum(!temp)) %>%
group_by(temp1) %>%
mutate(goal = +(row_number() == which.max(temp) & any(temp))) %>%
group_by(group) %>%
mutate(goal = ifelse(temp, cumsum(goal), NA)) %>%
select(-temp, -temp1)
# group criterium goal
# <fct> <lgl> <int>
# 1 A NA NA
# 2 A TRUE 1
# 3 A TRUE 1
# 4 A TRUE 1
# 5 A FALSE NA
# 6 A FALSE NA
# 7 A TRUE 2
# 8 A TRUE 2
# 9 A FALSE NA
#10 A TRUE 3
#11 A TRUE 3
#12 A TRUE 3
#13 B NA NA
#14 B FALSE NA
#15 B TRUE 1
#16 B TRUE 1
#17 B TRUE 1
#18 B FALSE NA
We first replace
NA
s in criterium
column to FALSE
and take cumulative sum over the negation of it (temp1
). We group_by
temp1
and assign 1 to every first TRUE
value in the group. Finally grouping by group
we take a cumulative sum for TRUE
values or return NA
for FALSE
and NA
values.
add a comment |
Maybe I have over-complicated this but one way with dplyr
is
library(dplyr)
df %>%
mutate(temp = replace(criterium, is.na(criterium), FALSE),
temp1 = cumsum(!temp)) %>%
group_by(temp1) %>%
mutate(goal = +(row_number() == which.max(temp) & any(temp))) %>%
group_by(group) %>%
mutate(goal = ifelse(temp, cumsum(goal), NA)) %>%
select(-temp, -temp1)
# group criterium goal
# <fct> <lgl> <int>
# 1 A NA NA
# 2 A TRUE 1
# 3 A TRUE 1
# 4 A TRUE 1
# 5 A FALSE NA
# 6 A FALSE NA
# 7 A TRUE 2
# 8 A TRUE 2
# 9 A FALSE NA
#10 A TRUE 3
#11 A TRUE 3
#12 A TRUE 3
#13 B NA NA
#14 B FALSE NA
#15 B TRUE 1
#16 B TRUE 1
#17 B TRUE 1
#18 B FALSE NA
We first replace
NA
s in criterium
column to FALSE
and take cumulative sum over the negation of it (temp1
). We group_by
temp1
and assign 1 to every first TRUE
value in the group. Finally grouping by group
we take a cumulative sum for TRUE
values or return NA
for FALSE
and NA
values.
Maybe I have over-complicated this but one way with dplyr
is
library(dplyr)
df %>%
mutate(temp = replace(criterium, is.na(criterium), FALSE),
temp1 = cumsum(!temp)) %>%
group_by(temp1) %>%
mutate(goal = +(row_number() == which.max(temp) & any(temp))) %>%
group_by(group) %>%
mutate(goal = ifelse(temp, cumsum(goal), NA)) %>%
select(-temp, -temp1)
# group criterium goal
# <fct> <lgl> <int>
# 1 A NA NA
# 2 A TRUE 1
# 3 A TRUE 1
# 4 A TRUE 1
# 5 A FALSE NA
# 6 A FALSE NA
# 7 A TRUE 2
# 8 A TRUE 2
# 9 A FALSE NA
#10 A TRUE 3
#11 A TRUE 3
#12 A TRUE 3
#13 B NA NA
#14 B FALSE NA
#15 B TRUE 1
#16 B TRUE 1
#17 B TRUE 1
#18 B FALSE NA
We first replace
NA
s in criterium
column to FALSE
and take cumulative sum over the negation of it (temp1
). We group_by
temp1
and assign 1 to every first TRUE
value in the group. Finally grouping by group
we take a cumulative sum for TRUE
values or return NA
for FALSE
and NA
values.
answered 54 mins ago
Ronak ShahRonak Shah
45.9k104268
45.9k104268
add a comment |
add a comment |
We can create a custom function via rle
, and use it per group, i.e.
f1 <- function(x)
x[is.na(x)] <- FALSE
rle1 <- rle(x)
y <- rle1$values
rle1$values[!y] <- 0
rle1$values[y] <- cumsum(rle1$values[y])
return(inverse.rle(rle1))
do.call(rbind,
lapply(split(df, df$group), function(i)!i$criterium, NA);
i))
Of course, If you want you can apply it via dplyr
, i.e.
library(dplyr)
df %>%
group_by(group) %>%
mutate(goal = f1(criterium),
goal = replace(goal, is.na(criterium)|!criterium, NA))
which gives,
# A tibble: 18 x 3
# Groups: group [2]
group criterium goal
<fct> <lgl> <dbl>
1 A NA NA
2 A TRUE 1
3 A TRUE 1
4 A TRUE 1
5 A FALSE NA
6 A FALSE NA
7 A TRUE 2
8 A TRUE 2
9 A FALSE NA
10 A TRUE 3
11 A TRUE 3
12 A TRUE 3
13 B NA NA
14 B FALSE NA
15 B TRUE 1
16 B TRUE 1
17 B TRUE 1
18 B FALSE NA
add a comment |
We can create a custom function via rle
, and use it per group, i.e.
f1 <- function(x)
x[is.na(x)] <- FALSE
rle1 <- rle(x)
y <- rle1$values
rle1$values[!y] <- 0
rle1$values[y] <- cumsum(rle1$values[y])
return(inverse.rle(rle1))
do.call(rbind,
lapply(split(df, df$group), function(i)!i$criterium, NA);
i))
Of course, If you want you can apply it via dplyr
, i.e.
library(dplyr)
df %>%
group_by(group) %>%
mutate(goal = f1(criterium),
goal = replace(goal, is.na(criterium)|!criterium, NA))
which gives,
# A tibble: 18 x 3
# Groups: group [2]
group criterium goal
<fct> <lgl> <dbl>
1 A NA NA
2 A TRUE 1
3 A TRUE 1
4 A TRUE 1
5 A FALSE NA
6 A FALSE NA
7 A TRUE 2
8 A TRUE 2
9 A FALSE NA
10 A TRUE 3
11 A TRUE 3
12 A TRUE 3
13 B NA NA
14 B FALSE NA
15 B TRUE 1
16 B TRUE 1
17 B TRUE 1
18 B FALSE NA
add a comment |
We can create a custom function via rle
, and use it per group, i.e.
f1 <- function(x)
x[is.na(x)] <- FALSE
rle1 <- rle(x)
y <- rle1$values
rle1$values[!y] <- 0
rle1$values[y] <- cumsum(rle1$values[y])
return(inverse.rle(rle1))
do.call(rbind,
lapply(split(df, df$group), function(i)!i$criterium, NA);
i))
Of course, If you want you can apply it via dplyr
, i.e.
library(dplyr)
df %>%
group_by(group) %>%
mutate(goal = f1(criterium),
goal = replace(goal, is.na(criterium)|!criterium, NA))
which gives,
# A tibble: 18 x 3
# Groups: group [2]
group criterium goal
<fct> <lgl> <dbl>
1 A NA NA
2 A TRUE 1
3 A TRUE 1
4 A TRUE 1
5 A FALSE NA
6 A FALSE NA
7 A TRUE 2
8 A TRUE 2
9 A FALSE NA
10 A TRUE 3
11 A TRUE 3
12 A TRUE 3
13 B NA NA
14 B FALSE NA
15 B TRUE 1
16 B TRUE 1
17 B TRUE 1
18 B FALSE NA
We can create a custom function via rle
, and use it per group, i.e.
f1 <- function(x)
x[is.na(x)] <- FALSE
rle1 <- rle(x)
y <- rle1$values
rle1$values[!y] <- 0
rle1$values[y] <- cumsum(rle1$values[y])
return(inverse.rle(rle1))
do.call(rbind,
lapply(split(df, df$group), function(i)!i$criterium, NA);
i))
Of course, If you want you can apply it via dplyr
, i.e.
library(dplyr)
df %>%
group_by(group) %>%
mutate(goal = f1(criterium),
goal = replace(goal, is.na(criterium)|!criterium, NA))
which gives,
# A tibble: 18 x 3
# Groups: group [2]
group criterium goal
<fct> <lgl> <dbl>
1 A NA NA
2 A TRUE 1
3 A TRUE 1
4 A TRUE 1
5 A FALSE NA
6 A FALSE NA
7 A TRUE 2
8 A TRUE 2
9 A FALSE NA
10 A TRUE 3
11 A TRUE 3
12 A TRUE 3
13 B NA NA
14 B FALSE NA
15 B TRUE 1
16 B TRUE 1
17 B TRUE 1
18 B FALSE NA
edited 28 mins ago
answered 49 mins ago
SotosSotos
31.3k51741
31.3k51741
add a comment |
add a comment |
A different dplyr
possibility using rle()
and dense_rank()
could be:
df %>%
group_by(group) %>%
mutate(rleid = with(rle(criterium), rep(seq_along(lengths), lengths))) %>%
group_by(group, criterium) %>%
mutate(res = dense_rank(rleid)) %>%
ungroup() %>%
mutate(res = ifelse(criterium, res, NA)) %>%
select(-rleid)
group criterium res
<fct> <lgl> <int>
1 A NA NA
2 A TRUE 1
3 A TRUE 1
4 A TRUE 1
5 A FALSE NA
6 A FALSE NA
7 A TRUE 2
8 A TRUE 2
9 A FALSE NA
10 A TRUE 3
11 A TRUE 3
12 A TRUE 3
13 B NA NA
14 B FALSE NA
15 B TRUE 1
16 B TRUE 1
17 B TRUE 1
18 B FALSE NA
add a comment |
A different dplyr
possibility using rle()
and dense_rank()
could be:
df %>%
group_by(group) %>%
mutate(rleid = with(rle(criterium), rep(seq_along(lengths), lengths))) %>%
group_by(group, criterium) %>%
mutate(res = dense_rank(rleid)) %>%
ungroup() %>%
mutate(res = ifelse(criterium, res, NA)) %>%
select(-rleid)
group criterium res
<fct> <lgl> <int>
1 A NA NA
2 A TRUE 1
3 A TRUE 1
4 A TRUE 1
5 A FALSE NA
6 A FALSE NA
7 A TRUE 2
8 A TRUE 2
9 A FALSE NA
10 A TRUE 3
11 A TRUE 3
12 A TRUE 3
13 B NA NA
14 B FALSE NA
15 B TRUE 1
16 B TRUE 1
17 B TRUE 1
18 B FALSE NA
add a comment |
A different dplyr
possibility using rle()
and dense_rank()
could be:
df %>%
group_by(group) %>%
mutate(rleid = with(rle(criterium), rep(seq_along(lengths), lengths))) %>%
group_by(group, criterium) %>%
mutate(res = dense_rank(rleid)) %>%
ungroup() %>%
mutate(res = ifelse(criterium, res, NA)) %>%
select(-rleid)
group criterium res
<fct> <lgl> <int>
1 A NA NA
2 A TRUE 1
3 A TRUE 1
4 A TRUE 1
5 A FALSE NA
6 A FALSE NA
7 A TRUE 2
8 A TRUE 2
9 A FALSE NA
10 A TRUE 3
11 A TRUE 3
12 A TRUE 3
13 B NA NA
14 B FALSE NA
15 B TRUE 1
16 B TRUE 1
17 B TRUE 1
18 B FALSE NA
A different dplyr
possibility using rle()
and dense_rank()
could be:
df %>%
group_by(group) %>%
mutate(rleid = with(rle(criterium), rep(seq_along(lengths), lengths))) %>%
group_by(group, criterium) %>%
mutate(res = dense_rank(rleid)) %>%
ungroup() %>%
mutate(res = ifelse(criterium, res, NA)) %>%
select(-rleid)
group criterium res
<fct> <lgl> <int>
1 A NA NA
2 A TRUE 1
3 A TRUE 1
4 A TRUE 1
5 A FALSE NA
6 A FALSE NA
7 A TRUE 2
8 A TRUE 2
9 A FALSE NA
10 A TRUE 3
11 A TRUE 3
12 A TRUE 3
13 B NA NA
14 B FALSE NA
15 B TRUE 1
16 B TRUE 1
17 B TRUE 1
18 B FALSE NA
answered 52 mins ago
tmfmnktmfmnk
3,7611516
3,7611516
add a comment |
add a comment |
A data.table
option using rle
library(data.table)
DT <- as.data.table(dat)
DT[, goal :=
r <- rle(replace(criterium, is.na(criterium), FALSE))
r$values <- with(r, cumsum(values) * values)
out <- inverse.rle(r)
replace(out, out == 0, NA)
, by = group]
DT
# group criterium goal
# 1: A NA NA
# 2: A TRUE 1
# 3: A TRUE 1
# 4: A TRUE 1
# 5: A FALSE NA
# 6: A FALSE NA
# 7: A TRUE 2
# 8: A TRUE 2
# 9: A FALSE NA
#10: A TRUE 3
#11: A TRUE 3
#12: A TRUE 3
#13: B NA NA
#14: B FALSE NA
#15: B TRUE 1
#16: B TRUE 1
#17: B TRUE 1
#18: B FALSE NA
data
dat <- structure(list(group = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("A",
"B"), class = "factor"), criterium = c(NA, TRUE, TRUE, TRUE,
FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, NA, FALSE,
TRUE, TRUE, TRUE, FALSE)), class = "data.frame", row.names = c(NA,
-18L))
Wow, impressive. Thanks for introducing me torle
andinverse.rle
. Gruß nach Leipzig.
– Humpelstielzchen
20 mins ago
@Humpelstielzchen Gern geschehen. Will try to simplify and explain the logic a bit.
– markus
16 mins ago
add a comment |
A data.table
option using rle
library(data.table)
DT <- as.data.table(dat)
DT[, goal :=
r <- rle(replace(criterium, is.na(criterium), FALSE))
r$values <- with(r, cumsum(values) * values)
out <- inverse.rle(r)
replace(out, out == 0, NA)
, by = group]
DT
# group criterium goal
# 1: A NA NA
# 2: A TRUE 1
# 3: A TRUE 1
# 4: A TRUE 1
# 5: A FALSE NA
# 6: A FALSE NA
# 7: A TRUE 2
# 8: A TRUE 2
# 9: A FALSE NA
#10: A TRUE 3
#11: A TRUE 3
#12: A TRUE 3
#13: B NA NA
#14: B FALSE NA
#15: B TRUE 1
#16: B TRUE 1
#17: B TRUE 1
#18: B FALSE NA
data
dat <- structure(list(group = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("A",
"B"), class = "factor"), criterium = c(NA, TRUE, TRUE, TRUE,
FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, NA, FALSE,
TRUE, TRUE, TRUE, FALSE)), class = "data.frame", row.names = c(NA,
-18L))
Wow, impressive. Thanks for introducing me torle
andinverse.rle
. Gruß nach Leipzig.
– Humpelstielzchen
20 mins ago
@Humpelstielzchen Gern geschehen. Will try to simplify and explain the logic a bit.
– markus
16 mins ago
add a comment |
A data.table
option using rle
library(data.table)
DT <- as.data.table(dat)
DT[, goal :=
r <- rle(replace(criterium, is.na(criterium), FALSE))
r$values <- with(r, cumsum(values) * values)
out <- inverse.rle(r)
replace(out, out == 0, NA)
, by = group]
DT
# group criterium goal
# 1: A NA NA
# 2: A TRUE 1
# 3: A TRUE 1
# 4: A TRUE 1
# 5: A FALSE NA
# 6: A FALSE NA
# 7: A TRUE 2
# 8: A TRUE 2
# 9: A FALSE NA
#10: A TRUE 3
#11: A TRUE 3
#12: A TRUE 3
#13: B NA NA
#14: B FALSE NA
#15: B TRUE 1
#16: B TRUE 1
#17: B TRUE 1
#18: B FALSE NA
data
dat <- structure(list(group = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("A",
"B"), class = "factor"), criterium = c(NA, TRUE, TRUE, TRUE,
FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, NA, FALSE,
TRUE, TRUE, TRUE, FALSE)), class = "data.frame", row.names = c(NA,
-18L))
A data.table
option using rle
library(data.table)
DT <- as.data.table(dat)
DT[, goal :=
r <- rle(replace(criterium, is.na(criterium), FALSE))
r$values <- with(r, cumsum(values) * values)
out <- inverse.rle(r)
replace(out, out == 0, NA)
, by = group]
DT
# group criterium goal
# 1: A NA NA
# 2: A TRUE 1
# 3: A TRUE 1
# 4: A TRUE 1
# 5: A FALSE NA
# 6: A FALSE NA
# 7: A TRUE 2
# 8: A TRUE 2
# 9: A FALSE NA
#10: A TRUE 3
#11: A TRUE 3
#12: A TRUE 3
#13: B NA NA
#14: B FALSE NA
#15: B TRUE 1
#16: B TRUE 1
#17: B TRUE 1
#18: B FALSE NA
data
dat <- structure(list(group = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("A",
"B"), class = "factor"), criterium = c(NA, TRUE, TRUE, TRUE,
FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, NA, FALSE,
TRUE, TRUE, TRUE, FALSE)), class = "data.frame", row.names = c(NA,
-18L))
edited 2 mins ago
answered 52 mins ago
markusmarkus
15.3k11336
15.3k11336
Wow, impressive. Thanks for introducing me torle
andinverse.rle
. Gruß nach Leipzig.
– Humpelstielzchen
20 mins ago
@Humpelstielzchen Gern geschehen. Will try to simplify and explain the logic a bit.
– markus
16 mins ago
add a comment |
Wow, impressive. Thanks for introducing me torle
andinverse.rle
. Gruß nach Leipzig.
– Humpelstielzchen
20 mins ago
@Humpelstielzchen Gern geschehen. Will try to simplify and explain the logic a bit.
– markus
16 mins ago
Wow, impressive. Thanks for introducing me to
rle
and inverse.rle
. Gruß nach Leipzig.– Humpelstielzchen
20 mins ago
Wow, impressive. Thanks for introducing me to
rle
and inverse.rle
. Gruß nach Leipzig.– Humpelstielzchen
20 mins ago
@Humpelstielzchen Gern geschehen. Will try to simplify and explain the logic a bit.
– markus
16 mins ago
@Humpelstielzchen Gern geschehen. Will try to simplify and explain the logic a bit.
– markus
16 mins ago
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55606323%2frank-groups-within-a-grouped-sequence-of-true-false-and-na%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown