У меня есть фрейм данных, который содержит возможные значения «c1», «c2», «c3» или «нет» для нескольких строк и нескольких столбцов. Любая заданная строка содержит либо «нет», либо только один других значений... то есть ни одна строка не содержит как c1, так и c2.
Что я хочу сделать, так это создать новый столбец, который содержит значение, отличное от «нет», для каждой строки, если Любые столбцов содержит значение, отличное от «нет»; в противном случае остается «нет». Думаю, это должно быть просто, но я не понимаю.
Вот пример данных... сохраните как "test1.csv"
Group1,Group2,Group3,Group4,Group5,Group6
c1,no,no,c1,no,no
no,no,c1,no,no,no
no,no,no,no,c1,no
no,no,no,no,no,no
c1,no,no,no,no,c1
no,c1,no,no,no,no
c2,no,no,no,no,no
no,c2,no,c2,no,no
no,no,no,no,no,no
no,no,no,no,no,c2
c3,no,c3,no,c3,no
no,no,no,no,no,no
no,no,c3,c3,no,no
Вот что я пытался сделать:
df <- read.csv("test1.csv")
df$any <- "no"
df$any[df == "c1"] <- "c1"
df$any[df == "c2"] <- "c2"
df$any[df == "c3"] <- "c3"
Что возвращает следующую ошибку:
Error in `$<-.data.frame`(`*tmp*`, any, value = c("c1", "no", "no", "no", :
replacement has 91 rows, data has 13
Успешный вывод должен выглядеть так:
Group1 Group2 Group3 Group4 Group5 Group6 any
1 c1 no no c1 no no c1
2 no no c1 no no no c1
3 no no no no c1 no c1
4 no no no no no no no
5 c1 no no no no c1 c1
6 no c1 no no no no c1
7 c2 no no no no no c2
8 no c2 no c2 no no c2
9 no no no no c2 no c2
10 no no no no no no no
11 c3 no c3 no c3 no c3
12 no no no no no no no
13 no no c3 c3 no no c3
Используя max.col
, мы можем извлечь первое значение в строке, которое не является "no"
. Поскольку каждая строка будет иметь одинаковое значение, отличное от «нет», связи здесь не будут иметь значения, или вы можете указать ties.method = "first"
, чтобы получить первое значение, отличное от «нет».
df$any <- df[cbind(1:nrow(df), max.col(df != "no"))]
df
# Group1 Group2 Group3 Group4 Group5 Group6 any
#1 c1 no no c1 no no c1
#2 no no c1 no no no c1
#3 no no no no c1 no c1
#4 no no no no no no no
#5 c1 no no no no c1 c1
#6 no c1 no no no no c1
#7 c2 no no no no no c2
#8 no c2 no c2 no no c2
#9 no no no no no no no
#10 no no no no no c2 c2
#11 c3 no c3 no c3 no c3
#12 no no no no no no no
#13 no no c3 c3 no no c3
Мы можем использовать метод base R
df1$any <- apply(df1, 1, function(x) x[x != 'no'][1])
df1$any[is.na(df1$any)] <- "no"
df1$any
#[1] "c1" "c1" "c1" "no" "c1" "c1" "c2" "c2" "c2" "no" "c3" "no" "c3"
Или другой вариант с pmin
в base R
df1$any <- do.call(pmin, df1)
df1$any
#[1] "c1" "c1" "c1" "no" "c1" "c1" "c2" "c2" "c2" "no" "c3" "no" "c3"
Или с dplyr
library(dplyr)
df1 %>%
mutate(any = pmin(!!! rlang::syms(names(.))))
Возможно, имеет смысл хранить ваши "no"
s как пропущенные значения, и в этом случае дополнительный столбец — это все остальные столбцы coalesce
d
library(dplyr)
df %>%
mutate_all(na_if, 'no') %>%
mutate(any = reduce(., coalesce))
# Group1 Group2 Group3 Group4 Group5 Group6 any
# 1 c1 <NA> <NA> c1 <NA> <NA> c1
# 2 <NA> <NA> c1 <NA> <NA> <NA> c1
# 3 <NA> <NA> <NA> <NA> c1 <NA> c1
# 4 <NA> <NA> <NA> <NA> <NA> <NA> <NA>
# 5 c1 <NA> <NA> <NA> <NA> c1 c1
# 6 <NA> c1 <NA> <NA> <NA> <NA> c1
# 7 c2 <NA> <NA> <NA> <NA> <NA> c2
# 8 <NA> c2 <NA> c2 <NA> <NA> c2
# 9 <NA> <NA> <NA> <NA> <NA> <NA> <NA>
# 10 <NA> <NA> <NA> <NA> <NA> c2 c2
# 11 c3 <NA> c3 <NA> c3 <NA> c3
# 12 <NA> <NA> <NA> <NA> <NA> <NA> <NA>
# 13 <NA> <NA> c3 c3 <NA> <NA> c3
@DanM Можете ли вы объяснить это на примере? В каком случае будут значения, отличные от значения в столбце, и какой результат вы ожидаете в этих случаях?