Как заменить ячейки дефиса в кадрах данных R нулями?

У меня есть фрейм данных с некоторыми положительными числами, некоторыми отрицательными числами, некоторыми словами и некоторыми дефисными «ячейками» в нем, как таковые:

Revenue                 73.88   74.76    78.02   78.19  68.74
Other Revenue - Total   -       -        -       -       -
Total Revenue           73.88   74.76    78.02   78.19  68.74
Cost of Revenue - Total 21.09   21.61    23.01   22.76  19.99
Gross Profit            52.80    -53.15  -55.01  55.43  48.75

Я хочу заменить дефисы, которые встречаются только в предпоследних столбцах, на 0, но только в том случае, если дефисы не находятся в начале чисел. Например, я не хочу превращать отрицательное число в положительное.

Я пытался:

df[-1] <- lapply(df[-1], function(x) as.numeric(gsub("-", 0, x)))

но это возвращает предыдущий кадр данных как:

Revenue                 NA      NA       NA      NA     NA
Other Revenue - Total   0       0        0       0      0
Total Revenue           NA      NA       NA      NA     NA
Cost of Revenue - Total NA      NA       NA      NA     NA
Gross Profit            NA      NA       NA      NA     NA 

чего я точно не хочу. Как я могу это исправить?

Спасибо.

Это вывод, когда я вызываю str():

str(income)
'data.frame':   49 obs. of  6 variables:
 $ Items  : Factor w/ 49 levels "Accounting Change",..: 44 40 47 7 23 45 43 9 29 49 ...
 $ Recent1: Factor w/ 14 levels "-","0.00","11,305.00",..: 4 1 4 11 14 6 5 1 1 1 ...
 $ Recent2: Factor w/ 16 levels "-","-29.00","0.00",..: 5 1 5 15 16 9 6 1 1 2 ...
 $ Recent3: Factor w/ 17 levels "-","0.00","11,449.00",..: 5 1 5 15 17 10 6 1 1 4 ...
 $ Recent4: Factor w/ 18 levels "-","-31.00","0.00",..: 6 1 6 15 17 9 4 1 1 18 ...
 $ Recent5: Factor w/ 14 levels "-","0.00","1,617.00",..: 4 1 4 10 13 5 3 1 1 1 ...

person user2395969    schedule 14.07.2014    source источник
comment
Являются ли эти столбцы числовыми? Подозреваю, что нет?   -  person Joe    schedule 15.07.2014
comment
Извините, я забыл упомянуть, что они являются факторами.   -  person user2395969    schedule 15.07.2014
comment
Почему они являются факторами? Они не очень похожи на факторы для меня. Они просто автоматически создаются для факторов, потому что ваш read.csv имеет набор stringsasfactors?   -  person Joe    schedule 15.07.2014
comment
Да, они были автоматически преобразованы в факторы программой read.xls.   -  person user2395969    schedule 15.07.2014


Ответы (2)


Предположим, что он называется dat:

  dat[2:6] <- lapply( dat[2:6], function(col) as.numeric( gsub("-$|\\,", "", col) ) )
  dat[is.na(dat)] <- 0

Заменяет только знаки минус в конце строки, удаляет запятые, а gsub приводит коэффициенты к символам, поэтому вам не нужно добавлять as.character. Когда я импортировал ваши данные, используя read.fwf и textConnection, я получил пробелы в конце. Вы можете использовать gdata::trim, чтобы сначала удалить их, но это сработало:

lapply(dat[2:6], function(col) as.numeric( gsub("-[ ]*$|\\,", "", col ) ) ) # on RHS 

 dat<-read.fwf(textConnection("Revenue                 73.88   74.76    78.02   78.19  68.74
 Other Revenue - Total   -       -        -       -       -
 Total Revenue           73.88   74.76    78.02   78.19  68.74
 Cost of Revenue - Total 21.09   21.61    23.01   22.76  19.99
 Gross Profit            52.80    -53.15  -55.01  55.43  48.75"), widths=c(24, rep(8,5)))

 dat[2:6] <- lapply( dat[2:6], function(col) as.numeric( gsub("-$|\\,", "", col) ) )
 dat[is.na(dat)] <- 0
 dat
#----------
                        V1    V2     V3     V4    V5    V6
1 Revenue                  73.88  74.76  78.02 78.19 68.74
2 Other Revenue - Total     0.00   0.00   0.00  0.00  0.00
3 Total Revenue            73.88  74.76  78.02 78.19 68.74
4 Cost of Revenue - Total  21.09  21.61  23.01 22.76 19.99
5 Gross Profit             52.80 -53.15 -55.01 55.43 48.75
person IRTFM    schedule 15.07.2014

Как намекнул @Joe, значения в столбце data.frame должны быть одного типа, поэтому, учитывая, что у вас есть - в тех же векторах, что и numeric (52.80, 21.09 и т. д.), каждый столбец вынужден вводить character (предположительно). Попробуйте gsubсвязать с "0" вместо 0, а затем преобразовать столбцы в numeric. Поскольку вы принудительно вставляете 0 в вектор-столбец character, остальные элементы вектора принуждаются к NA.

DF <- data.frame(
  X1=c(12,45,67,"-",9),
  X2=c(34,45,56,"-",12))
str(DF)
'data.frame':   5 obs. of  2 variables:
 $ X1: chr  "12" "45" "67" "-" ...
 $ X2: chr  "34" "45" "56" "-" ...
##
DF2 <- DF
DF2$X1 <- gsub("-","0",DF2$X1)
DF2$X1 <- as.numeric(DF2$X1)
str(DF2)
'data.frame':   5 obs. of  2 variables:
 $ X1: num  12 45 67 0 9
 $ X2: chr  "34" "45" "56" "-" ...

РЕДАКТИРОВАТЬ: Чтобы удалить запятые в ваших значениях,

DF <- data.frame(
  X0=c("A","B","C","D"),
  X1=c("12,300.04","45.5","-","9,046.78"),
  X2=c("1,0001.12","33","-","12.6"))
for(j in 2:ncol(DF)){
  DF[,j] <- gsub(",","",as.character(DF[,j]))
  for(i in 1:nrow(DF)){
    if(nchar(DF[i,j])==1){
      DF[i,j] <- gsub("-","0",DF[i,j])
    } else {
      next
    }
  }
  DF[,j] <- as.numeric(DF[,j])
  DF[,j]
}

Есть более эффективные способы сделать это с помощью *apply функций и регулярных выражений, но это должно работать. Мне пришлось учесть тот факт, что некоторые из ваших значений отрицательны, поэтому, если предположить, что ячейки, содержащие только -, имеют длину только один символ, это должно исправить их, не затрагивая отрицательные значения в других ячейках.

person nrussell    schedule 14.07.2014
comment
Я только что попробовал это, и это не сработало. Это дало мне те же результаты, что и в прошлый раз, с NA. Мой фрейм данных изначально был фреймом данных факторов, и даже когда я преобразовал их в символы, я все равно получил те же результаты. - person user2395969; 15.07.2014
comment
Это странно, я попробовал это с моими примерными данными выше и не получил никаких значений NA. Можете ли вы вызвать str() в своем data.frame и опубликовать вывод, пожалуйста? - person nrussell; 15.07.2014
comment
Ах, я думаю, что это запятые в некоторых ваших значениях, которые изначально не отображались. Позвольте мне добавить некоторый код в конец моего ответа, чтобы я мог правильно отформатировать его. Момент. - person nrussell; 15.07.2014