Как использовать if-оператор в функции apply? - PullRequest
0 голосов
/ 09 апреля 2019

Поскольку мне нужно прочитать более 3-х ходов данных, я хотел бы улучшить свой код, изменив два for-loop и if-statement на функцию apply.

Здесь приведен воспроизводимый пример моего кода. Общая цель (в этом примере) - подсчитать количество положительных и отрицательных значений в столбце «c» для каждого значения x и y. В реальном случае у меня есть более 150 файлов для чтения.

# Example of initial data set
df1 <- data.frame(a=rep(c(1:5),times=3),b=rep(c(1:3),each=5),c=rnorm(15))
# Another dataframe to keep track of "c" counts
dfOcc <- data.frame(a=rep(c(1:5),times=3),"positive"=c(0),"negative"=c(0))

Пока что я сделал этот код, который работает, но очень медленно:

for (i in 1:nrow(df)) {
  x = df[i,"a"]
  y = df[i,"b"]
  if (df[i,"c"]>=0) {
    dfOcc[which(dfOcc$a==x && dfOcc$b==y),"positive"] <- dfOcc[which(dfOcc$a==x && dfOcc$b==y),"positive"] +1
  }else{
    dfOcc[which(dfOcc$a==x && dfOcc$b==y),"negative"] <- dfOcc[which(dfOcc$a==x && dfOcc$b==y),"negative"] +1
  }
}

Я не уверен, что код медленный из-за размера файлов (260 тыс. Строк каждый) или из-за for-loop?

Пока мне удалось улучшить его следующим образом:

dfOcc[which(dfOcc$a==df$a & dfOcc$b==df$b),"positive"] <- apply(df,1,function(x){ifelse(x["c"]>0,1,0)})

Это прекрасно работает в этом примере, но не в моем реальном случае:

  • Он учитывает только положительные значения c, и выполнение этого кода дважды может привести к обратным результатам
  • Мои исходные наборы данных имеют 260 тыс. Строк, а мой "трассировщик" - 10 тыс. Строк (исходный набор данных повторяет значения a и b с другими значениями c

Буду признателен за любые советы по улучшению этих двух пунктов!

Ответы [ 2 ]

0 голосов
/ 09 апреля 2019

package data.table может помочь вам сделать это в одной строке.

df1 <-  data.table(data.frame(a=rep(c(1:5),times=3),b=rep(c(1:3),each=5),c=rnorm(15)))
posneg <- c("positive" , "negative") # list of columns needed
df1[,(posneg) := list(ifelse(c>0, 1,0), ifelse(c<0, 1,0))] # use list to combine the 2 ifelse conditions


для получения дополнительной информации, попробуйте

?data.table

, если вы действительно хотите, чтобы положительные отрицательные значения были вотдельный фрейм данных,

dfOcc <- df1[,c("a", "positive","negative")]
0 голосов
/ 09 апреля 2019

Я думаю, вы можете просто считать и распространять данные.Это будет проще и будет работать с любой группой и набором данных.Вы можете изменить group_by(a) на group_by(a, b), если хотите сосчитать группировку столбцов a и b.

library(dplyr)
library(tidyr)

df1 %>% 
    group_by(a) %>% 
    mutate(sign = ifelse(c > 0, "Positive", "Negative")) %>% 
    count(sign) %>% 
    spread(sign, n)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...