2015-03-06 11 views
7

Chciałbym utworzyć nową kolumnę, która jest równa maksymalnej wartości wszystkich kolumn tego wiersza.Obliczyć maksymalne wiersze

Oto przykład:

library(data.table) 
data <- data.table(head(iris)) 
data[ , Species := NULL] 
data 

    Sepal.Length Sepal.Width Petal.Length Petal.Width 
1:   5.1   3.5   1.4   0.2 
2:   4.9   3.0   1.4   0.2 
3:   4.7   3.2   1.3   0.2 
4:   4.6   3.1   1.5   0.2 
5:   5.0   3.6   1.4   0.2 
6:   5.4   3.9   1.7   0.4 

nie mogę korzystać z funkcji max tutaj, ponieważ ma zamiar znaleźć maksymalną wartość wszystkich kolumn, np data[, max_value := max(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width)]. Co chcę jest coś takiego:

Sepal.Length Sepal.Width Petal.Length Petal.Width max_value 
1:   5.1   3.5   1.4   0.2  5.1 
2:   4.9   3.0   1.4   0.2  4.9 
3:   4.7   3.2   1.3   0.2  4.7 
4:   4.6   3.1   1.5   0.2  4.6 
5:   5.0   3.6   1.4   0.2  5.0 
6:   5.4   3.9   1.7   0.4  5.4 
+1

czuję się jak matryca jest lepsze przechowywanie tutaj , ale są "dane [, mymax: = apply (.SD, 1, max)]", które wymyślają do macierzy jako kroku pośredniego. – Frank

Odpowiedz

7

nie będę ręczyć za jego szybkość, ale przynajmniej unika zmuszanie do matrycy:

data[,mymax:=do.call(pmax,.SD)] 
+0

W jaki sposób otrzymasz drugi maks., Trzeci lub n-ty maks z odpowiedzi. – Deepesh

+0

@ Deepesh Wymagane podejście do tego jest całkiem inne, jak sądzę. Może będziesz musiał szukać więcej lub opublikować nowe pytanie. – Frank

6

Korzystanie dplyr można zrobić:

library(dplyr) 
setDF(data) %>% 
    rowwise() %>% 
    mutate(max = max(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width)) 

#Source: local data frame [10 x 5] 
#Groups: <by row> 
# 
# Sepal.Length Sepal.Width Petal.Length Petal.Width max 
#1   5.1   3.5   1.4   0.2 5.1 
#2   4.9   3.0   1.4   0.2 4.9 
#3   4.7   3.2   1.3   0.2 4.7 
#4   4.6   3.1   1.5   0.2 4.6 
#5   5.0   3.6   1.4   0.2 5.0 
#6   5.4   3.9   1.7   0.4 5.4 

Albo jak @akrun zasugerował:

setDF(data) %>% mutate(max=pmax(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width)) 

Który znacznie szybciej niż podejście rowwise():

n <- 10e6; nc <- 4; DT <- data.table(replicate(nc,rnorm(n))) 

mbm <- microbenchmark(
    steven = DT %>% rowwise() %>% mutate(V5 = max(V1, V2, V3, V4)), 
    frank = DT[,c(.SD,list(do.call(pmax,.SD)))], 
    akrun = DT %>% mutate(V5 = pmax(V1, V2, V3, V4)), times = 25, unit = "relative") 

enter image description here

#Unit: relative 
# expr  min  lq  mean median  uq  max neval cld 
# steven 17.93647 18.024734 17.535764 17.42948 17.484920 16.446384 25 b 
# frank 1.00000 1.000000 1.000000 1.00000 1.000000 1.000000 25 a 
# akrun 1.00220 1.002281 1.013604 1.00240 1.003089 1.001262 25 a 
+4

Można również użyć 'pmax' tj.' SetDF (data)%>% mutate (max = pmax (Sepal.Length, Sepal.Width, Petal.Length, Petal.Width)) ' – akrun

+0

@akrun Tak, zdecydowanie lepiej opcja. –

+0

Ta fabuła jest całkiem schludna; czy możesz dołączyć polecenie użyte do zrobienia tego? Kiedy usuwam 'setDT' \' setDF' (którego nie rozumiem włączenia) i ': =' (aby uczynić go porównywalnym z liniami dplyr, które nie modyfikują DT), wydajność jest podobna. 'n <- 10e6; nc <- 4; DT <- data.table (replikuj (nc, rnorm (n))); microbenchmark (frank = DT [, c (.SD, list (do.call (pmax, .SD)))], akrun = DT%>% mutacji (V5 = pmax (V1, V2, V3, V4)), razy = 10), identyczne (frank, akrun) 'Dunno dlaczego wynik jest inny – Frank

3

użytku by=1:nrow(data) do grupy według wierszy:

data[, max_value:=max(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width), by=1:nrow(data)] 

data 
    Sepal.Length Sepal.Width Petal.Length Petal.Width max_value 
1:   5.1   3.5   1.4   0.2  5.1 
2:   4.9   3.0   1.4   0.2  4.9 
3:   4.7   3.2   1.3   0.2  4.7 
4:   4.6   3.1   1.5   0.2  4.6 
5:   5.0   3.6   1.4   0.2  5.0 
6:   5.4   3.9   1.7   0.4  5.4 
+0

To jest inteligentny sposób używania 'by'. Dzięki! – Boxuan