Сопоставление имен переменных со значениями переменных в R - PullRequest
1 голос
/ 28 марта 2020

У меня есть фрейм данных со следующими переменными:

date=c("30/03/2018","30/03/2018","30/03/2018","30/03/2018","30/03/2018","30/03/2018","30/03/2018","30/03/2018")
hour=c(1,1,1,1,2,2,2,2)
location=c(North,South,East,West,North,South,East,West)
North=c(10,30,40,50,0,40,31,11)
South=c(20,10,20,0,0,0,5,0)
East=c(0,10,10,5,0,0,5,0)
West=c(5,30,40,50,0,40,31,11)
df <- data.frame(date, hour, location, North, South, East, West)

location представляет место, где наблюдается наблюдение. Столбцы North, South, East и West показывают среднее количество осадков в этих регионах. Во-первых, мне нужно создать столбец Actual, чтобы изобразить количество осадков в location. Например, для строки 1 значение для Actual будет равно 10, поскольку оно находится на севере. Затем мне нужно создать два других столбца, High1 и High2. Первый представляет наибольшее количество осадков в оставшихся 3 регионах за этот час, а второй представляет второе по величине количество осадков в оставшихся 3 регионах. Например, для строки 1 значения для High1 и High2 равны 20 и 5 соответственно, поскольку в этот час у Юга и Запада самые высокие и вторые самые высокие зарегистрированные значения.

Есть ли рекомендуемая команда (с), что я мог бы использовать для этой настройки? Спасибо.

Ответы [ 3 ]

1 голос
/ 29 марта 2020

Вы можете использовать следующий код, который использует функцию nth из пакета Rfast , чтобы получить второе по величине количество осадков в остальных регионах.

library(Rfast)

NSEW <- grep("North|South|East|West", names(df))
i.col <- sapply(df$location, function(x) grep(x, names(df)))
df$Actual <- as.numeric(df[cbind(1:nrow(df), i.col)])   
df[cbind(1:nrow(df), i.col)] <- 0         
df$High1 <- apply(df[,NSEW], 1, max) # *       
df$High2 <- apply(df[,NSEW], 1, Rfast::nth, k=2, descending=TRUE) # *
df[cbind(1:nrow(df), i.col)] <- df$Actual   
df

        date hour location North South East West Actual High1 High2
1 30/03/2018    1    North    10    20    0    5     10    20     5
2 30/03/2018    1    South    30    10   10   30     10    30    30
3 30/03/2018    1     East    40    20   10   40     10    40    40
4 30/03/2018    1     West    50     0    5   50     50    50     5
5 30/03/2018    2    North     0     0    0    0      0     0     0
6 30/03/2018    2    South    40     0    0   40      0    40    40
7 30/03/2018    2     East    31     5    5   31      5    31    31
8 30/03/2018    2     West    11     0    0   11     11    11     0

* Также можно использовать rownth, который возвращает n-е наименьшее значение для каждой строки:

df$High1 <- Rfast::rownth(as.matrix(df[,NSEW]), elems=rep(1, nrow(df)), descending=TRUE)
df$High2 <- Rfast::rownth(as.matrix(df[,NSEW]), elems=rep(2, nrow(df)), descending=TRUE)
1 голос
/ 28 марта 2020

Попробуйте это (я уверен, что есть много более простых решений):

library(tidyverse)

df %>%
  left_join(
    df %>%
      mutate(n = row_number()) %>%
      pivot_longer(North:West, names_to = "loc", values_to = "rainfall") %>%
      group_by(n) %>%
      mutate(actual = max(ifelse(location==loc,rainfall,0))) %>%
      filter(location != loc) %>%
      arrange(-rainfall) %>%
      mutate(high = paste0("High", row_number())) %>%
      filter(row_number() < 3) %>%
      select(-loc, -n) %>%
      pivot_wider(names_from = high, values_from = rainfall)  %>%
      ungroup() %>%
      arrange(n) %>% select(-n) )

#         date hour location North South East West actual High1 High2
# 1 30/03/2018    1    North    10    20    0    5     10    20     5
# 2 30/03/2018    1    South    30    10   10   30     10    30    30
# 3 30/03/2018    1     East    40    20   10   40     10    40    40
# 4 30/03/2018    1     West    50     0    5   50     50    50     5
# 5 30/03/2018    2    North     0     0    0    0      0     0     0
# 6 30/03/2018    2    South    40     0    0   40      0    40    40
# 7 30/03/2018    2     East    31     5    5   31      5    31    31
# 8 30/03/2018    2     West    11     0    0   11     11    11     0

Данные

date <- c("30/03/2018","30/03/2018","30/03/2018","30/03/2018","30/03/2018","30/03/2018","30/03/2018","30/03/2018")
hour <- c(1,1,1,1,2,2,2,2)
location <- c("North","South","East","West","North","South","East","West")
North <- c(10,30,40,50,0,40,31,11)
South <- c(20,10,20,0,0,0,5,0)
East <- c(0,10,10,5,0,0,5,0)
West <- c(5,30,40,50,0,40,31,11)
df <- data.frame(date, hour, location, North, South, East, West)
0 голосов
/ 28 марта 2020

Если вы не хотите использовать Tidyverse, вот альтернатива:

date <- c("30/03/2018","30/03/2018","30/03/2018","30/03/2018","30/03/2018","30/03/2018","30/03/2018","30/03/2018")
hour <- c(1,1,1,1,2,2,2,2)
loc <- c("North","South","East","West","North","South","East","West")
North <- c(10,30,40,50,0,40,31,11)
South <- c(20,10,20,0,0,0,5,0)
East <- c(0,10,10,5,0,0,5,0)
West <- c(5,30,40,50,0,40,31,11)
location <- list(North, South, East, West, North, South, East, West)



actual <- numeric(length(location))
High1 <- numeric(length(location))
High2 <- numeric(length(location))
for (i in 1:length(location)){
  actual[i] <- (location[[i]][i])
  location[[i]][i] <- 0
  High1[i] <- max(sapply(location , `[` , i))
}
short_location <- location[c(1:4)]
for (i in 1:length(location)){
  n <- length(short_location)
  High2[i] <- sort(sapply(short_location , `[` , i), partial=n-1)[n-1]
}
df <- data.frame(date, hour, loc, North, South, East, West, actual, High1, High2)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...