Learner
Learner

Reputation: 757

how to get median for specific columns

I have a data like this

df<-structure(list(T = c(36034L, 63763L, 51432L, 65100L, 61444L, 
71012L, 266610L, 389787L, 47659L, 63156L, 84593L, 84331L), T.1 = c(45632L, 
66505L, 60360L, 36685L, 107551L, 53360L, 323952L, 344944L, 69601L, 
51268L, 130665L, 59704L), T.2 = c(59025L, 52837L, 68571L, 35788L, 
75262L, 66601L, 424683L, 340948L, 79487L, 42809L, 95607L, 81739L
), BG = c(74767L, 48210L, 70972L, 67705L, 85576L, 89265L, 393380L, 
306633L, 77816L, 73611L, 106317L, 116890L), BG.1 = c(50846L, 
37970L, 63896L, 78296L, 81216L, 62308L, 62613L, 21770L, 80955L, 
88832L, 97586L, 68345L), BG.2 = c(26688L, 27830L, 17010L, 54074L, 
26727L, 31109L, 24448L, 38701L, 17378L, 46327L, 25324L, 25325L
), TR = c(16498L, 26604L, 41201L, 38417L, 43709L, 33217L, 69943L, 
80638L, 37444L, 31701L, 46781L, 31152L), TR.1 = c(16272L, 24485L, 
14546L, 74756L, 28193L, 770L, 72238L, 78418L, 9161L, 48618L, 
26466L, 1078L), TR.2 = c(20612L, 713L, 18114L, 57872L, 25684L, 
27985L, 73618L, 1770L, 11953L, 33347L, 25824L, 25860L)), row.names = c("A", 
"B", "C", "D", "E", "F", "A_Mo1", "B_Mo1", "C_Mo1", "D_Mo1", 
"E_Mo1", "F_Mo1"), class = "data.frame")

I am trying to get median for each row based on each 3 columns. I have tried many things but without success.

first ways

apply(df, 2, FUN = median)

another way

dataused <- c("1:3","4:6","7:9")
medians <- sapply(dataused,function(y)
  c(by(df[,eval(parse(text=y))],median(unlist(x)))))

Upvotes: 1

Views: 486

Answers (4)

M--
M--

Reputation: 28850

You can do it in base using apply family functions.

t(apply(df1, 1, tapply, gl(3, 3), median, na.rm = TRUE))

#>            1     2     3
#> A      45632 50846 16498
#> B      63763 37970 24485
#> C      60360 63896 18114
#> D      36685 67705 57872
#> E      75262 81216 28193
#> F      66601 62308 27985
#> A_Mo1 323952 62613 72238
#> B_Mo1 344944 38701 78418
#> C_Mo1  69601 77816 11953
#> D_Mo1  51268 73611 33347
#> E_Mo1  95607 97586 26466
#> F_Mo1  81739 68345 25860

Upvotes: 2

indubitably
indubitably

Reputation: 297

You could use dplyr and rowwise()

df %>% rowwise() %>% mutate(T_median = median(T, T.1, T.2), BG_median = median(BG, BG.1,BG.2), TR_median = median(TR, TR.1, TR.2))



        T    T.1    T.2     BG  BG.1  BG.2    TR  TR.1  TR.2 T_median BG_median TR_median
    <int>  <int>  <int>  <int> <int> <int> <int> <int> <int>    <int>     <int>     <int>
 1  36034  45632  59025  74767 50846 26688 16498 16272 20612    36034     74767     16498
 2  63763  66505  52837  48210 37970 27830 26604 24485   713    63763     48210     26604
 3  51432  60360  68571  70972 63896 17010 41201 14546 18114    51432     70972     41201
 4  65100  36685  35788  67705 78296 54074 38417 74756 57872    65100     67705     38417
 5  61444 107551  75262  85576 81216 26727 43709 28193 25684    61444     85576     43709
 6  71012  53360  66601  89265 62308 31109 33217   770 27985    71012     89265     33217
 7 266610 323952 424683 393380 62613 24448 69943 72238 73618   266610    393380     69943
 8 389787 344944 340948 306633 21770 38701 80638 78418  1770   389787    306633     80638
 9  47659  69601  79487  77816 80955 17378 37444  9161 11953    47659     77816     37444
10  63156  51268  42809  73611 88832 46327 31701 48618 33347    63156     73611     31701
11  84593 130665  95607 106317 97586 25324 46781 26466 25824    84593    106317     46781
12  84331  59704  81739 116890 68345 25325 31152  1078 25860    84331    116890     31152

Upvotes: 1

JdeMello
JdeMello

Reputation: 1718

You didn't specify which columns you wish to calculate the median for. But you can use apply with the MARGIN argument as 1 which does the operations by row. Depending on the size of your data.frame, it could be slightly inefficient. Assuming you want to do this for the first three columns:

cols <- c("T", "T.1", "T.2")

newCols <- paste0("median_", paste0(cols, collapse = "_"))

df[[newCols]] <- apply(df[, cols], MARGIN=1, FUN=median)

Result:

> df
           T    T.1    T.2     BG  BG.1  BG.2    TR  TR.1  TR.2 median_T_T.1_T.2
A      36034  45632  59025  74767 50846 26688 16498 16272 20612            45632
B      63763  66505  52837  48210 37970 27830 26604 24485   713            63763
C      51432  60360  68571  70972 63896 17010 41201 14546 18114            60360
D      65100  36685  35788  67705 78296 54074 38417 74756 57872            36685
E      61444 107551  75262  85576 81216 26727 43709 28193 25684            75262
F      71012  53360  66601  89265 62308 31109 33217   770 27985            66601
A_Mo1 266610 323952 424683 393380 62613 24448 69943 72238 73618           323952
B_Mo1 389787 344944 340948 306633 21770 38701 80638 78418  1770           344944
C_Mo1  47659  69601  79487  77816 80955 17378 37444  9161 11953            69601
D_Mo1  63156  51268  42809  73611 88832 46327 31701 48618 33347            51268
E_Mo1  84593 130665  95607 106317 97586 25324 46781 26466 25824            95607
F_Mo1  84331  59704  81739 116890 68345 25325 31152  1078 25860            81739

For completeness, with data.table:

cols <- c("T", "T.1", "T.2")
newCols <- paste0("median_", paste0(cols, collapse = "_"))
df[, (newCols) := apply(.SD, 1, median), .SDcols=cols]

Upvotes: 1

akrun
akrun

Reputation: 887118

One option is rowMedians

library(matrixStats)
sapply(list(as.matrix(df[1:3]), as.matrix(df[4:6]), as.matrix(df[7:9])), rowMedians)

Or using base R only

nm1 <-  sub("\\.\\d+$", "", names(df))
df[paste0(unique(nm1), "_median")] <- sapply(split.default(df, nm1),
            function(x) apply(x, MARGIN = 1, FUN = median))

Or split based on the pattern in column names

library(stringr)
library(dplyr)
library(purrr)
df %>% 
   split.default(str_remove(names(.), "\\.\\d+$")) %>%
    map_df(~ as.matrix(.x) %>% 
                  rowMedians)
# A tibble: 12 x 3
#      BG      T    TR
#   <dbl>  <dbl> <dbl>
# 1 50846  45632 16498
# 2 37970  63763 24485
# 3 63896  60360 18114
# 4 67705  36685 57872
# 5 81216  75262 28193
# 6 62308  66601 27985
# 7 62613 323952 72238
# 8 38701 344944 78418
# 9 77816  69601 11953
#10 73611  51268 33347
#11 97586  95607 26466
#12 68345  81739 25860

Upvotes: 2

Related Questions