Сортировка подмножества столбцов для каждой строки

Я хочу отсортировать my.data[4:10] в порядке убывания по строке. Здесь есть некоторые подсказки, но я не смог их достаточно разобрать: Отсортируйте столбцы со второго по пятый для каждой строки в R.

Я также пробовал такие вещи, как:

sort(my.data, decreasing = TRUE, partial = c([4:10]))

что не сработало, но я думаю, что первое больше соответствует тому, что мне нужно. Я прочитал справки по ?cbind, ?apply и ?sort, но примеры для меня слишком загадочны.

Вот мой пример набора данных:

habitat<-c('Marsh','Prairie','Savanna','Swamp','Woodland')
NumSites<-c(3,3,4,1,4)
NumSamples<-c(6,5,8,2,8)
Sp1<-c(NA,2,NA,2,1)
Sp2<-c(NA,2,1,NA,1)
Sp3<-c(NA,NA,NA,NA,1)
Sp4<-c(3,NA,NA,NA,NA)
Sp5<-c(NA,NA,3,NA,NA)
Sp6<-c(1,NA,67,NA,2)
Sp7<-c(NA,2,3,NA,1)

my.data<-data.frame(habitat,NumSites,NumSamples,Sp1,Sp2,Sp3,Sp4,Sp5,Sp6,Sp7)

# I suspect a varient of this must work:
# cbind(df[,1], t(apply(df[,-1], 1, sort)))

желаемый результат должен выглядеть так:

habitat  NumSites NumSamples Sp1 Sp2 Sp3 Sp4 Sp5 Sp6 Sp7
Marsh    3        6          3   1   NA  NA  NA  NA  NA
Prairie  3        5          2   2   2   NA  NA  NA  NA
Savanna  4        8          67  3   3   1   NA  NA  NA
Swamp    1        2          2   NA  NA  NA  NA  NA  NA
Woodland 4        8          2   1   1   1   1   NA  NA

Я чувствую, что подход cbind близок...

Кроме того, фактические данные имеют много и разное количество столбцов и имен столбцов, поэтому я хочу использовать диапазон [4:10] вместо имен столбцов.


person Steve T    schedule 01.09.2014    source источник


Ответы (3)


Подход к этому ответу, который вы цитируете выше, близок:

cbind(df[,1], t(apply(df[,-1], 1, sort)))

но потребовалось два изменения:

  • Вы хотите отсортировать все, кроме первых трех столбцов, а не все, кроме первого. Поэтому измените [,1] и [,-1] на [, 1:3] и [, -(1:3)] соответственно.
  • По умолчанию sort сортирует в порядке возрастания, в то время как вы хотите в порядке убывания, и полностью отбрасывает NA, пока вы хотите, чтобы они были последними. Вы можете исправить это, добавив аргументы decreasing=TRUE, na.last=TRUE к sort.

Это делает решение:

cbind(my.data[, 1:3], t(apply(my.data[, -(1:3)], 1, function(v) sort(v, decreasing=TRUE, na.last=TRUE))))

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

mysort = function(v) sort(v, decreasing=TRUE, na.last=TRUE)
sorted.cols = t(apply(my.data[, -(1:3)], 1, mysort))
cbind(my.data[, 1:3], sorted.cols)
person David Robinson    schedule 01.09.2014

Кажется, это работает нормально:

my.data[,4:10] <- t(apply(my.data[,4:10], 1,  function(x) sort(x, na.last = T, decreasing=T)))


#   habitat NumSites NumSamples Sp1 Sp2 Sp3 Sp4 Sp5 Sp6 Sp7
#1    Marsh        3          6   3   1  NA  NA  NA  NA  NA
#2  Prairie        3          5   2   2   2  NA  NA  NA  NA
#3  Savanna        4          8  67   3   3   1  NA  NA  NA
#4    Swamp        1          2   2  NA  NA  NA  NA  NA  NA
#5 Woodland        4          8   2   1   1   1   1  NA  NA
person jalapic    schedule 01.09.2014
comment
Анонимная функция не нужна. В подмножестве не должно быть запятых, если мы имеем дело с фреймами данных. - person Rich Scriven; 01.09.2014

Вам не нужна анонимная функция.

> my.data[4:10] <-t(apply(my.data[4:10],1,sort,decreasing = TRUE,na.last = TRUE))
> my.data
#    habitat NumSites NumSamples Sp1 Sp2 Sp3 Sp4 Sp5 Sp6 Sp7
# 1    Marsh        3          6   3   1  NA  NA  NA  NA  NA
# 2  Prairie        3          5   2   2   2  NA  NA  NA  NA
# 3  Savanna        4          8  67   3   3   1  NA  NA  NA
# 4    Swamp        1          2   2  NA  NA  NA  NA  NA  NA
# 5 Woodland        4          8   2   1   1   1   1  NA  NA
person Rich Scriven    schedule 01.09.2014