R: Выберите ячейки в data.frame на основе другого атрибута в том же экземпляре - PullRequest
1 голос
/ 14 ноября 2010

Хорошо, заголовок может быть не самым описательным. Это проще объяснить на примере.

У меня есть data.frame, как это:

A B 1 2
L M 3 0
P Q 5 6

Я хочу вывести массив ячейки в столбце 1, если col3> col4, или ячейку в col2, если col3 <= col4. Выходной вектор из этого data.frame будет <code>B, L, Q.

Я знаю, что я до сих пор не очень хорошо объяснил свою проблему, поэтому вот как она будет выглядеть на императивном языке:

vector = []
for each rows as row
  if row[3] > row[4]
    vector.add(row[1])
  else
    vector.add(row[2])
return vector

Я прошу прощения, если эта проблема уже была решена, но, к сожалению, Google не очень помогает, когда речь идет о вопросах R.

Спасибо, Andreas

Ответы [ 2 ]

4 голосов
/ 14 ноября 2010

Ваш тестовый пример недостаточно сложен, чтобы раскрыть некоторые скрывающиеся крокодилы в R, относящиеся к объектам класса == factor, опциям по умолчанию для data.frame () и использованию таких функций, как apply и ifelse.Я мог бы извиниться за длину ответа, но на самом деле это всего лишь небольшое подмножество того, что вы можете прочитать в The Inferno .Допустим, вы создали data.frame, dfrm:

dfrm <-data.frame(textConnection("A  B  2  12
L  M  3  0
P  Q  5  6", header=FALSE)

ВНИМАНИЕ: я немного изменил ваш первый случай.Теперь запустите первое предложенное решение: вы получите

 apply(dfrm, 1, function(x){ifelse(x[3] > x[4], x[1], x[2])})
[1] "A" "L" "P"

Очевидно, что 2 НЕ больше 12, так что же случилось?Функция apply работает с матрицами и преобразует data.frame в матрицу перед выполнением функции и проверяет «2»> «12», что равно TRUE.Таким образом, крокодил # 1 является поведением по умолчанию apply ().

Ошибки или предупреждения также являются результатом того, что может показаться на первый и второй взгляд совершенно разумным кодом R:

vector <- dfrm$V2; 
vector[V3 > V4] <- V1[V3 > V4]

(Во всяком случае, для меня это не было особенно информативным сообщением об ошибке ... кое-что о NA ... и это было связано с тем, что я пытался присвоить значение факторному объекту, для которого не было существующего уровня.) Это второй крокодил: класс по умолчанию для символьных значений, данных функции data.frame, это «фактор», а не «символ».

Третий крокодил - это поведение ifelse:

 with(dfrm, ifelse(V3 > V4, V1, V2) )
[1] 1 2 3

WTF?Функция ifelse автоматически преобразует факторы в V1 и V2 в их внутренние числовые представления, и это происходит потому, что функция принудительно возвращает возвращаемые значения на основе типа условных аргументов.Не так, как я бы разработал такую ​​функцию, но эти вещи были разработаны десятилетия назад, поэтому их изменение почти невозможно.Итак, пара «правильных» или, по крайней мере, более безопасных способов выполнения работы, которую вы просили: Метод 1:

with(dfrm, ifelse(V3 > V4, as.character(V1), as.character(V2) ) )  
[1] "B" "L" "Q"

Метод 2:

vector <- as.character(dfrm$V2)  
vector[which(dfrm$V3 > dfrm$V4)] <- as.character(dfrm$V1[which(dfrm$V3 > dfrm$V4)])  
vector  
[1] "B" "L" "Q"
3 голосов
/ 14 ноября 2010

Это должно работать (при условии, что df - ваш фрейм данных)

apply(df, 1, function(x){ifelse(x[3] > x[4], x[1], x[2])})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...