Заменить определенный символ и разделить остаток - PullRequest
0 голосов
/ 06 июля 2018

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

Date <- c("2013-01-01","2013-01-10","2013-01-16","2013-01-19")
concentration1 <- c("12","<10","<2","14")
concentration2 <- c("10","<10","<5","15")
y <- data.frame(Date, concentration1,concentration2)
y$Date <- as.Date(y$Date)

Мне нужно найти во фрейме данных символ «<», удалить его и разделить остаток на 2. Я пытался получить результат с помощью следующего кода: </p>

y <- data.frame(lapply(y, function(x) {
  gsub("<", "", x)
 }))

Однако я не смог разделить остаток на 2.

UPDATE:

Это мой оригинальный код с моими данными, основанными на ответе @RHertel:

hw13<-read.csv("https://www.dropbox.com/s/dw6fket1b0bmoll/HW2013_%20Doemitz.csv?dl=1",sep=";",header=TRUE)

hw13$Datum<-as.Date(hw13$Datum, format="%d.%m.%Y")#convert to date
hw13[] <- lapply(hw13, as.character)     
hw13[sapply(hw13, startsWith, "<")] <- as.numeric(substring(hw13[sapply(hw13, startsWith, "<")],2)) / 2

Ответы [ 4 ]

0 голосов
/ 06 июля 2018

Можно определить записи, которые необходимо изменить с помощью sapply в сочетании с startsWith, и выполнить необходимые операции (удалить <, преобразовать в числовое значение, разделить на 2) для этих элементов.

y[] <- lapply(y, as.character)     
y[sapply(y, startsWith, "<")] <- as.numeric(substring(y[sapply(y, startsWith, "<")],2)) / 2

#> y
#        Date concentration1 concentration2
#1 2013-01-01             12             10
#2 2013-01-10              5              5
#3 2013-01-16              1            2.5
#4 2013-01-19             14             15

Столбцы 2 и 3, содержащие концентрации, можно преобразовать в числовые значения следующим образом:

y[2:3] <- sapply(y[2:3], as.numeric)
0 голосов
/ 06 июля 2018
y[2:3] <- lapply(y[2:3],function(x){
  x <- as.character(x) # if it's a factor
  flag    <- startsWith(x,"<")
  x       <- as.numeric(gsub("^<","",x))
  x[flag] <- x[flag] / 2
  x
})

#          Date concentration1 concentration2
# 1 2013-01-01             12           10.0
# 2 2013-01-10              5            5.0
# 3 2013-01-16              1            2.5
# 4 2013-01-19             14           15.0
0 голосов
/ 06 июля 2018

1) Вам нужно запомнить индекс полей с '<' </p>

2) Удалите «<», как предложено </p>

3) разделить на 2

4) снова преобразовать дату в формат даты

idx=lapply(y, function(x) grep("<",x) )
y=lapply(y, function(x) gsub("<", "", x)) 
y=data.frame(mapply(function(x,i){if(length(i)>0) x[i]=as.numeric(x[i])/2; x},y ,idx ))
y$Date <- as.Date(y$Date)

Результат:

        Date concentration1 concentration2
1 2013-01-01             12             10
2 2013-01-10              5              5
3 2013-01-16              1            2.5
4 2013-01-19             14             15
0 голосов
/ 06 июля 2018

Как упоминает Стивен, вам нужно преобразовать в числовые

data.frame(y[1], lapply(y[-1], function(x) as.numeric(gsub("<", "", x)) / 2))

#         Date concentration1 concentration2
# 1 2013-01-01              6            5.0
# 2 2013-01-10              5            5.0
# 3 2013-01-16              1            2.5
# 4 2013-01-19              7            7.5

В ответ на комментарии.

Сначала убедитесь, что строки читаются как символы при создании data.frame. Затем избегайте циклов (или * применяйте), конвертируя в матрицу, и пусть R выполняет векторизованную магию Это не перезапишет исходный файл data.frame, а создаст новый.

y <- data.frame(Date, concentration1, concentration2, stringsAsFactors=FALSE)
y$Date <- as.Date(y$Date)

val <- as.matrix(y[,-1])
ind <- startsWith(val, "<")
val[ind] <- as.numeric(sub("<", "", val[ind])) / 2
data.frame(y[1], val)

#         Date concentration1 concentration2
# 1 2013-01-01             12             10
# 2 2013-01-10              5              5
# 3 2013-01-16              1            2.5
# 4 2013-01-19             14             15
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...