以下是我正在使用的数据的迷你版本:
columnNum <- c("G1", "G2", "G3")
Al <- c("<5", 6, 7, "<4", 5, 6)
Ca <- c(9, 10, 11,10, 11, 12)
df <- data.frame(columnNum, Al, Ca, stringsAsFactors = FALSE)
目前,由于某些值被审查(包含"<"),每列的类都是字符、字符、数字(按从左到右的顺序)
我想做的是将"Al"列中的值替换为实际的数值,而不是字符串。我确信我可以找到一种方法,只为一个专栏做这件事,但我的问题是,实际上,我有20个不同的专栏,而不是2个。我需要浏览每一列(从"Al"列到"Zn"列),检查值是否经过审查,如果是,去掉"<"并将其转换为数字。
我还是个新手,所以这就是我试图做的(在我的大数据上,而不是这个小数据上):
for(i in df$Al:df$Zn)
{
if (class(df[[i]]) != numeric)
{
df[[i]] <- as.numeric(gsub(pattern = "<", replacement =
"", df[[i]]))
}
}
循环永远不会结束。
我们应该首先找到要调整的列。我们根据您对从Al
到Zn
的列的描述来执行此操作。接下来,我们sub
不必要的字符,并使用numerize
函数转换为numeric
。我添加了更多的列来显示复杂性:
cols <- match("Al", names(df)):match("Zn", names(df))
numerize <- function(x) as.numeric(sub(".*?([0-9.-]+).*", "\1", x))
#base R
df[cols] <- lapply(df[cols], numerize)
#dplyr
df %>% mutate_at(vars(Al:Zn), numerize)
#data.table
setDT(df)[, (names(df)[cols]) := lapply(.SD, numerize), .SDcols=cols][]
# columnNum Al Yw Zn Ca
# 1 G1 5 8 1 9
# 2 G2 6 6 6 10
# 3 G3 7 7 7 11
# 4 G1 4 4 4 10
# 5 G2 5 5 5 11
# 6 G3 6 6 6 12
数据
columnNum <- c("G1", "G2", "G3")
Al <- c("<5", 6, 7, "<4", 5, 6)
Yw <- c("<8", 6, 7, "<4", 5, 6)
Zn <- c("<1", 6, 7, "<4", 5, 6)
Ca <- c(9, 10, 11,10, 11, 12)
df <- data.frame(columnNum, Al, Yw, Zn, Ca, stringsAsFactors = FALSE)
tidyr::extract_numeric
很方便,无论是否在dplyr
中:
df$Al <- tidyr::extract_numeric(Al) # or df %>% mutate(Al = extract_numeric(Al))
大致相当于
df$Al <- as.numeric(sub('.*(-?[0-9]+.?[0-9]*).*', '\1', df$Al))
对于这种特殊情况,可以简化为:
df$Al <- as.integer(sub('<', '', df$Al))
无论您使用哪种数据,您都可以获得以下数据:
## columnNum Al Ca
## 1 G1 5 9
## 2 G2 6 10
## 3 G3 7 11
## 4 G1 4 10
## 5 G2 5 11
## 6 G3 6 12