Bryan Han
Bryan Han

Reputation: 67

rowMeans if column name is number

I have datafram that looks like:

Data i have looks like..

 Tester Type    Subject Type    Time        1     2     3
 TType1         SType1          Day 1       11    2     1         
 TType1         SType2          Day 1       3     2     13
 TType1         SType1          Day 2       2     3     15
 TType2         SType3          Day 2       1     4     3
 TType3         SType3          Day 2       2     3     4
 TType1         SType1          Day 1       7     2     2
 TType2         SType1          Day 2       2     6     7

so the column names I have is c(Tester.Type, Subject.Type, Time, 1, 2, 3)

I want to create a column that calculates row means, but only when column name is numeric.

I know how to do it straight off like:

avgdata <- rowMeans(data[,c(4:6)],na.rm=TRUE)

But is there a way to code so it automatically picks up if column names are number (is.numeric)?

So that way if I have more columns with numeric column names, I dont have to change column ranges?

Thank you.

Upvotes: 3

Views: 315

Answers (3)

DrPositron
DrPositron

Reputation: 187

Building upon @Ven Yao's answer, to create a column of rowMeans using mutate:

require(dplyr)
df1 <- read.table(text="
TesterType    SubjectType    Time        1     2     3
TType1         SType1          Day1       11    2     1
TType1         SType2          Day1       3     2     13
TType1         SType1          Day2       2     3     15
TType2         SType3          Day2       1     4     3
TType3         SType3          Day2       2     3     4
TType1         SType1          Day1       7     2     2
TType2         SType1          Day2       2     6     7",
                  head=T, as.is=T, check.names=F)

l<-which(!is.na(as.numeric(colnames(df1))))
df1 <- df1 %>%
  mutate(rowmean = apply(select(.,unlist(l)),1,mean))
df1
  TesterType SubjectType Time  1 2  3  rowmean
1     TType1      SType1 Day1 11 2  1 4.666667
2     TType1      SType2 Day1  3 2 13 6.000000
3     TType1      SType1 Day2  2 3 15 6.666667
4     TType2      SType3 Day2  1 4  3 2.666667
5     TType3      SType3 Day2  2 3  4 3.000000
6     TType1      SType1 Day1  7 2  2 3.666667
7     TType2      SType1 Day2  2 6  7 5.000000

Upvotes: 2

akrun
akrun

Reputation: 887223

It is not good to use column names that start with numbers. We can change it to append a prefix 'X' using make.names

rowMeans(df1[grep('^X', make.names(names(df1)))])
#[1] 4.666667 6.000000 6.666667 2.666667 3.000000 3.666667 5.000000

Or using dplyr

library(dplyr)
df1 %>% 
    select(matches('^\\d+')) %>%
    Reduce(`+`, .)/3

Upvotes: 1

Ven Yao
Ven Yao

Reputation: 3710

When you read in your data. Remember to use the parameter check.names=F.

df1 <- read.table(text="
TesterType    SubjectType    Time        1     2     3
TType1         SType1          Day1       11    2     1
TType1         SType2          Day1       3     2     13
TType1         SType1          Day2       2     3     15
TType2         SType3          Day2       1     4     3
TType3         SType3          Day2       2     3     4
TType1         SType1          Day1       7     2     2
TType2         SType1          Day2       2     6     7",
                 head=T, as.is=T, check.names = F)

df1
rowMeans(df1[colnames(df1)[!is.na(as.numeric(colnames(df1)))]])
# [1] 4.666667 6.000000 6.666667 2.666667 3.000000 3.666667 5.000000

or using regular expression.

rowMeans(df1[colnames(df1)[grepl("^\\d+$", colnames(df1))]])
# [1] 4.666667 6.000000 6.666667 2.666667 3.000000 3.666667 5.000000

Upvotes: 2

Related Questions