我有一个 dataframe ,如下所示:
df_start <- data.frame(
a = c(1, 1, 1, 1, 1),
b = c(0, 1, 0, 0, 0),
c = c(1, 0, 0, 0, 0),
n = c(0, 0, 0, 1, 0))
我想测试条件,如果来自df_start[,2:n]
的任何列(其中n显示数据帧的最后一列)等于df$a
,那么创建两个新列,其中第一列如果条件为TRUE则返回1,如果不是则返回0,另一个给出条件为TRUE的列的名称。
我设法创建了第一列:
library(dplyr)
# check condition
df_start <- df_start %>% mutate(cond = ifelse(a == b | a == c | a == n, 1, 0))
即使我认为我需要一种不同的方法,因为每次都可能有不同的列数。所以我需要测试列a
的条件以及从2到最后一列的所有列,但我还需要知道条件满足哪一列。
期望的输出:
# desired output
df_end <- data.frame(a = c(1, 1, 1, 1, 1),
b = c(0, 1, 0, 0, 0),
c = c(1, 0, 0, 0, 0),
n = c(0, 0, 0, 1, 0),
cond = c(1,1,0,1,0),
col_name = c("c", "b", NA, "n", NA))
有没有办法用dplyr
或基础R来做到这一点?虽然任何其他解决方案都很受欢
答案 0 :(得分:2)
另一个基础R解决方案:
m <- df_start[,1] == df_start[,2:4]
df_start$cond <- rowSums(m)
df_start$col_name[!!rowSums(m)] <- names(df_start[2:4])[max.col(m) * rowSums(m)]
给出:
> df_start a b c n cond col_name 1 1 0 1 0 1 c 2 1 1 0 0 1 b 3 1 0 0 0 0 <NA> 4 1 0 0 1 1 n 5 1 0 0 0 0 <NA>
答案 1 :(得分:1)
以下仅使用基础R.
请注意,要创建列JAVA_OPTS
,不需要cond
。
ifelse
答案 2 :(得分:1)
您可以尝试tidyverse
。我喜欢将gather
和spread
用于此类方法。
library(tidyverse)
df_start %>%
rownames_to_column() %>%
gather(k, v, -a, -rowname) %>%
group_by(rowname) %>%
mutate(cond=ifelse(any(a==v), 1, 0)) %>%
mutate(col_name=ifelse(cond==1, k[v==1], NA)) %>%
ungroup() %>%
spread(k, v) %>%
select(-rowname)
# A tibble: 5 x 6
a cond col_name b c n
<dbl> <dbl> <chr> <dbl> <dbl> <dbl>
1 1 1 c 0 1 0
2 1 1 b 1 0 0
3 1 0 NA 0 0 0
4 1 1 n 0 0 1
5 1 0 NA 0 0 0
或者不转换像
这样的管道/应用解决方案df_start %>%
mutate(col_name=apply(.[-1], 1, function(x, y) y[x==1], colnames(.)[-1])) %>%
mutate(cond=as.numeric(apply(.[-ncol(.)], 1, function(x) any(x[1] == x[-1]))))
a b c n col_name cond
1 1 0 1 0 c 1
2 1 1 0 0 b 1
3 1 0 0 0 0
4 1 0 0 1 n 1
5 1 0 0 0 0
答案 3 :(得分:0)
很好的解决方案@Jimbou与tidyverse。完成后,您可以通过更改Jimbous代码中的最后一行来安排结果:
select(-c(rowname, cond, col_name), c(cond, col_name))