这似乎是一个简单的问题,但我很难理解它。我有一个按出生地区划分的人口位置数据框,我正在尝试筛选总人口超过阈值(在本例中为 50%)的地区。
例如,对于每个位置,我需要能够说“在费尔菲尔德县,大多数外国出生的人口出生在中美洲、南美洲或加勒比地区。”为了能够以这种方式表述,我需要包括第一个超过 50% 标记的国家/地区。
我的数据的删节版本以及每个位置的前几行位于此处:
library(tidyverse)
df <- structure(list(name = c("Fairfield County", "Fairfield County",
"Fairfield County", "Fairfield County", "Greater Hartford", "Greater Hartford",
"Greater Hartford", "Greater Hartford", "Greater Hartford"),
subregion = c("South America", "Central America", "Caribbean",
"South Central Asia", "Caribbean", "Eastern Europe", "South Central Asia",
"South America", "Southern Europe"),
pop = c(40565, 33919, 32044, 17031, 26939, 23765, 20153, 14384, 9309),
cum_share = c(0.2, 0.38, 0.54, 0.62, 0.2, 0.37, 0.51, 0.62, 0.69)),
class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -9L))
df %>%
group_by(name) %>%
top_n(4, pop)
#> # A tibble: 8 x 4
#> # Groups: name [2]
#> name subregion pop cum_share
#> <chr> <chr> <dbl> <dbl>
#> 1 Fairfield County South America 40565 0.2
#> 2 Fairfield County Central America 33919 0.38
#> 3 Fairfield County Caribbean 32044 0.54
#> 4 Fairfield County South Central Asia 17031 0.62
#> 5 Greater Hartford Caribbean 26939 0.2
#> 6 Greater Hartford Eastern Europe 23765 0.37
#> 7 Greater Hartford South Central Asia 20153 0.51
#> 8 Greater Hartford South America 14384 0.62
我的第一个计划是过滤累计份额小于或等于 51% 的地区,即排名靠前的地区,直到达到大多数人口。问题在于,由于这些份额不是连续分布,因此设置这样的截止点是行不通的,因为我需要包括累积份额占多数的第一个区域。
df %>%
filter(cum_share <= 0.51)
#> # A tibble: 5 x 4
#> name subregion pop cum_share
#> <chr> <chr> <dbl> <dbl>
#> 1 Fairfield County South America 40565 0.2
#> 2 Fairfield County Central America 33919 0.38
#> 3 Greater Hartford Caribbean 26939 0.2
#> 4 Greater Hartford Eastern Europe 23765 0.37
#> 5 Greater Hartford South Central Asia 20153 0.51
通过与第一个快照的比较,您可以看到,大哈特福德的工作正如我所期望的那样。但费尔菲尔德县应该包括加勒比地区,其累计份额为 54%;通过设置 51% 的阈值进行过滤,加勒比地区不包括在内。我想要得到的是这样的:
#> # A tibble: 6 x 4
#> name subregion pop cum_share
#> <chr> <chr> <dbl> <dbl>
#> 1 Fairfield County South America 40565 0.2
#> 2 Fairfield County Central America 33919 0.38
#> 3 Fairfield County Caribbean 32044 0.54
#> 4 Greater Hartford Caribbean 26939 0.2
#> 5 Greater Hartford Eastern Europe 23765 0.37
#> 6 Greater Hartford South Central Asia 20153 0.51
这里,还包括份额超过50%的第一名。我可以手动过滤,但实际上我是按国家/地区而不是世界地区进行此操作,并且针对 18 个位置,因此它变得很笨拙。
提前致谢!
编辑:哇,我意识到自己的愚蠢了 - 我可以按升序顺序计算人口的累积份额,而不是降序 ,然后轻松过滤该阈值超过 50% 的地方。不过,我将保留这一点,以帮助那些无法通过这种方式控制数据的人。
最佳答案
For example, for each location I need to be able to say something like, "In Fairfield County, a majority of the foreign-born population were born in Central and South America or the Caribbean."
对于满足条件后停止的一般情况,有 filter(lag(cumsum(cond), default=FALSE) == 0)
> df %>% group_by(name) %>% filter(cumsum(lag(cum_share > 0.5, default = FALSE)) == 0)
# A tibble: 6 x 4
# Groups: name [2]
name subregion pop cum_share
<chr> <chr> <dbl> <dbl>
1 Fairfield County South America 40565 0.20
2 Fairfield County Central America 33919 0.38
3 Fairfield County Caribbean 32044 0.54
4 Greater Hartford Caribbean 26939 0.20
5 Greater Hartford Eastern Europe 23765 0.37
6 Greater Hartford South Central Asia 20153 0.51
OP 在单调条件的情况下确定了一个更简单的过滤器(即,在第一次满足条件后,向量的后续元素也这样做):filter(lag(cum_share, default = 0) <= 0.5)
.
可能有一个很好的方法将其包装在函数中(根据用户输入改变 .cond
;改变 .keep
标准 = cumsum(lag(.cond, default=FALSE) == 0)
;过滤器;删除 .cond
和 .keep
),但我没有tidyverse NSE 技能是第一步。
关于r - 按阈值过滤数据,包括第一个超过阈值的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51827428/