如何在数据框中找到前 n% 的记录并将其更改为 1,否则为 0
How to find top n% of records in a dataframe and change it to 1, otherwise 0
我有这样一个数据框:
v1 v2 v2 v4 v5 v6 v7 v8
1 10 8 8 50 19 41 20
11 21 87 67 23 49 14 0
88 24 55 67 24 67 56 90
我想要的是,如果值在所有值的前5%或10%,则改为1;
如果不是,则替换为 0。
结构如下:(这不是真实的结果,只是显示我想要得到的结构)
0 0 0 0 1 0 0 1
0 0 1 0 0 0 0 1
0 1 0 0 1 0 0 1
有什么快速的方法吗?我的数据大约是60*639
这个有用吗:
df
# A tibble: 3 x 8
v1 v2 v2_1 v4 v5 v6 v7 v8
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 10 8 8 50 19 41 20
2 11 21 87 67 23 49 14 0
3 88 24 55 67 24 67 56 90
df[] <- lapply(df, function(x) +(x > quantile(sort(unlist(df)), 0.95, names = F)))
df
# A tibble: 3 x 8
v1 v2 v2_1 v4 v5 v6 v7 v8
<int> <int> <int> <int> <int> <int> <int> <int>
1 0 0 0 0 0 0 0 0
2 0 0 0 0 0 0 0 0
3 1 0 0 0 0 0 0 1
在基数 R 中:
1*(as.matrix(df) > quantile(unlist(df), 0.95))
#> v1 v2 v2.1 v4 v5 v6 v7 v8
#> [1,] 0 0 0 0 0 0 0 0
#> [2,] 0 0 0 0 0 0 0 0
#> [3,] 1 0 0 0 0 0 0 1
另一种选择是将数据透视值延长,然后按组排列。较低的前 5 个将分配在前 5 行。然后你计算一个二进制变量并重塑为宽(不确定前 5 个是否可以理解为前 5 个元素或其他东西。我也通过某种意义上的“行”进行了计算):
library(dplyr)
library(tidyr)
#Function
newdf <- df %>% mutate(id=row_number()) %>%
pivot_longer(-id) %>%
arrange(id,value) %>%
group_by(id) %>%
mutate(Var=ifelse(row_number()<=5,0,1)) %>%
select(-value) %>%
pivot_wider(names_from=name,values_from=Var) %>%
ungroup() %>% select(-id)
输出:
# A tibble: 3 x 8
v1 v3 v4 v2 v6 v8 v7 v5
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 0 0 0 0 0 1 1 1
2 0 1 1 0 1 0 0 0
3 1 0 0 0 1 1 0 0
一个dplyr
选项可以是:
df %>%
mutate(across(everything(), ~ as.numeric(. > quantile(unlist(df), 0.95))))
v1 v2 v2.1 v4 v5 v6 v7 v8
1 0 0 0 0 0 0 0 0
2 0 0 0 0 0 0 0 0
3 1 0 0 0 0 0 0 1
我有这样一个数据框:
v1 v2 v2 v4 v5 v6 v7 v8
1 10 8 8 50 19 41 20
11 21 87 67 23 49 14 0
88 24 55 67 24 67 56 90
我想要的是,如果值在所有值的前5%或10%,则改为1; 如果不是,则替换为 0。 结构如下:(这不是真实的结果,只是显示我想要得到的结构)
0 0 0 0 1 0 0 1
0 0 1 0 0 0 0 1
0 1 0 0 1 0 0 1
有什么快速的方法吗?我的数据大约是60*639
这个有用吗:
df
# A tibble: 3 x 8
v1 v2 v2_1 v4 v5 v6 v7 v8
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 10 8 8 50 19 41 20
2 11 21 87 67 23 49 14 0
3 88 24 55 67 24 67 56 90
df[] <- lapply(df, function(x) +(x > quantile(sort(unlist(df)), 0.95, names = F)))
df
# A tibble: 3 x 8
v1 v2 v2_1 v4 v5 v6 v7 v8
<int> <int> <int> <int> <int> <int> <int> <int>
1 0 0 0 0 0 0 0 0
2 0 0 0 0 0 0 0 0
3 1 0 0 0 0 0 0 1
在基数 R 中:
1*(as.matrix(df) > quantile(unlist(df), 0.95))
#> v1 v2 v2.1 v4 v5 v6 v7 v8
#> [1,] 0 0 0 0 0 0 0 0
#> [2,] 0 0 0 0 0 0 0 0
#> [3,] 1 0 0 0 0 0 0 1
另一种选择是将数据透视值延长,然后按组排列。较低的前 5 个将分配在前 5 行。然后你计算一个二进制变量并重塑为宽(不确定前 5 个是否可以理解为前 5 个元素或其他东西。我也通过某种意义上的“行”进行了计算):
library(dplyr)
library(tidyr)
#Function
newdf <- df %>% mutate(id=row_number()) %>%
pivot_longer(-id) %>%
arrange(id,value) %>%
group_by(id) %>%
mutate(Var=ifelse(row_number()<=5,0,1)) %>%
select(-value) %>%
pivot_wider(names_from=name,values_from=Var) %>%
ungroup() %>% select(-id)
输出:
# A tibble: 3 x 8
v1 v3 v4 v2 v6 v8 v7 v5
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 0 0 0 0 0 1 1 1
2 0 1 1 0 1 0 0 0
3 1 0 0 0 1 1 0 0
一个dplyr
选项可以是:
df %>%
mutate(across(everything(), ~ as.numeric(. > quantile(unlist(df), 0.95))))
v1 v2 v2.1 v4 v5 v6 v7 v8
1 0 0 0 0 0 0 0 0
2 0 0 0 0 0 0 0 0
3 1 0 0 0 0 0 0 1