Как вычесть столбец из других столбцов в кадре данных
У меня есть фрейм данных, который состоит из 1000 строк и 156 столбцов. Я пытаюсь вычесть первый столбец из следующих 38 столбцов, затем вычесть столбец 39 из следующих 38 и так далее, но я не могу найти способ сделать это. Я использую только ncdf4 и ничего больше. Что-то вроде этого
C1 C2 C3 C4 C5 C6 C7 C8
1 2 3 4 5 6 4 5
3 4 6 5 4 3 2 7
И я бы хотел, чтобы это было
C1 C2 C3 C4 C5 C6 C7 C8
0 1 2 3 4 5 3 4
0 1 3 2 1 0 -1 4
Логика будет первые 38 столбцов - первый столбец
Столбцы 39:77 - Столбец 39
и так далее.
4 ответа
Решил это просто делая
{
z[,1:38] <- z[,1:38]-z[,1]
z[,39:77] <-z[,39:77]-z[,39]
z[,78:118] <-z[,78:118]-z[,78]
z[,119:156] <-z[,119:156]-z[,119]
}
Где z - это датафрейм. Может быть, это не самый хороший способ, но он добился цели
Вы должны рассмотреть возможность использования tidyverse
Чтобы решить эту проблему, загрузка пакета в R мало влияет на издержки вашей среды и может значительно облегчить вашу жизнь.
library(tidyverse)
> df %>%
mutate_at(.vars = vars(num_range(prefix = 'C', 1:38)), .funs = function(x) x - .$C1) %>%
mutate_at(.vars = vars(num_range(prefix = 'C', 39:77)), .funs = function(x) x - .$C39)
C1 C2 C3 C4 C38 C39 C40 C41 C42 C77
1 0 1 2 3 4 0 1 2 3 4
2 0 0 3 2 4 0 0 3 2 4
Данные
df <-
data.frame(
C1 = c(1, 3),
C2 = c(2, 3),
C3 = c(3, 6),
C4 = c(4, 5),
C38 = c(5, 7),
C39 = c(1, 3),
C40 = c(2, 3),
C41 = c(3, 6),
C42 = c(4, 5),
C77 = c(5, 7)
)
Вот определенная пользователем функция: Вы можете добавить else, если операторы по желанию.
mydiff<-function(df){
mydiff<-df
for(i in 1:ncol(df)){
if(i<=38){
mydiff[,i]<-df[,i]-df[,1]
}
else if(i%in%c(39:77)){
mydiff[,i]<-df[,i]-df[,39]
}
}
mydiff
}
mydiff(df1)
Выход:
C1 C2 C3 C4 C5 C6 C7 C8
0 1 2 3 4 5 3 4
0 1 3 2 1 0 -1 4
Ориентир:
system.time(result<-as.tibble(iris2) %>%
select_if(is.numeric) %>%
mydiff())
Результат:
user system elapsed
0.02 0.00 0.01
Вы также можете сделать следующее без цикла:
# sample data frame
df <- data.frame(matrix(data = seq(1,316),ncol = 158))
# split the data frame into list of data frame having columns
# 1 to 38, 39 to 77 and so on
df <- split.default(df, gl(round(ncol(df)/38),k = 38))
# subtract the last column from each
df <- do.call(cbind, lapply(df, function(f) f - f[,ncol(f)]))
colnames(df) <- paste0('C', seq(1,158))
print(head(df))
C1 C2 C3 C4 C5
1 -74 -72 -70 -68 -66
2 -74 -72 -70 -68 -66