보이지 않는 문자열 값이있는 새 레코드를 데이터 프레임에 추가 할 때 보이지 않는 요인 수준으로 인해 경고가 발생하고 NA가 발생합니다.
2001 년부터 2007 년까지의 청구 데이터를 포함하는 데이터 프레임 (14.5K 행 x 15 열)이 있습니다.
새로운 2008 데이터를 다음과 같이 추가합니다. alltime <- rbind(alltime,all2008)
불행히도 경고를 생성합니다.
> Warning message:
In `[<-.factor`(`*tmp*`, ri, value = c(NA, NA, NA, NA, NA, NA, NA, :
invalid factor level, NAs generated
내 생각 엔 이전 데이터 프레임에 이름이 없었던 새로운 환자가있어서 어떤 수준을 제공해야할지 모를 것입니다. 마찬가지로 '추천 의사'열에 보이지 않는 새로운 이름이 있습니다.
해결책은 무엇입니까?
두 가지 유형의 불일치로 인해 발생할 수 있습니다 data.frames
.
먼저 모든 검사 유형 (클래스). 진단 목적으로 다음을 수행하십시오.
new2old <- rbind( alltime, all2008 ) # this gives you a warning
old2new <- rbind( all2008, alltime ) # this should be without warning
cbind(
alltime = sapply( alltime, class),
all2008 = sapply( all2008, class),
new2old = sapply( new2old, class),
old2new = sapply( old2new, class)
)
다음과 같은 행이있을 것으로 예상합니다.
alltime all2008 new2old old2new
... ... ... ... ...
some_column "factor" "numeric" "factor" "character"
... ... ... ... ...
그렇다면 설명 : rbind
유형이 일치하는지 확인하지 마십시오. rbind.data.frame
코드를 분석 하면 첫 번째 인수가 출력 유형을 초기화했음을 알 수 있습니다. 첫 번째 data.frame 유형이 요인 인 경우 출력 data.frame 열은 수준이있는 요인입니다 unique(c(levels(x1),levels(x2)))
. 두 번째 data.frame 열에서 다음 요인이없는 때 levels(x2)
이다 NULL
, 그래서 레벨이 확장되지 않습니다.
출력 데이터가 잘못되었음을 의미합니다! 있다 NA
진정한 값 대신이야 '
나는 그것을 가정한다 :
- 다른 R / RODBC 버전으로 이전 데이터를 생성하므로 유형이 다른 방법으로 생성되었습니다 (다른 설정-소수점 구분 기호 일 수 있음).
- 문제가있는 열에 NULL 또는 일부 특정 데이터가 있습니다. 누군가 데이터베이스에서 열을 변경합니다.
해결책:
잘못된 열을 찾아서 그 이유가 잘못되고 수정 된 이유를 찾습니다. 증상이 아닌 원인을 제거하십시오.
"쉬운"방법은 텍스트 데이터를 가져올 때 문자열을 요소로 설정하지 않는 것입니다.
참고 것으로 read.{table,csv,...}
기능은 걸릴 stringsAsFactors
에 기본 설정입니다 매개 변수를 TRUE
. 데이터를 FALSE
가져오고 rbind
- 하는 동안 이것을로 설정할 수 있습니다 .
마지막에 열을 요소로 설정하려면 그렇게 할 수도 있습니다.
예를 들면 :
alltime <- read.table("alltime.txt", stringsAsFactors=FALSE)
all2008 <- read.table("all2008.txt", stringsAsFactors=FALSE)
alltime <- rbind(alltime, all2008)
# If you want the doctor column to be a factor, make it so:
alltime$doctor <- as.factor(alltime$doctor)
1) stringsAsFactor를 FALSE로 설정하여 데이터 프레임을 만듭니다. 이것은 요인 문제를 해결해야합니다
2) 나중에 rbind를 사용하지 마십시오. 데이터 프레임이 비어 있으면 열 이름이 엉망이됩니다. 이렇게하면됩니다.
df[nrow(df)+1,] <- c("d","gsgsgd",4)
/
> df <- data.frame(a = character(0), b=character(0), c=numeric(0))
> df[nrow(df)+1,] <- c("d","gsgsgd",4)
Warnmeldungen:
1: In `[<-.factor`(`*tmp*`, iseq, value = "d") :
invalid factor level, NAs generated
2: In `[<-.factor`(`*tmp*`, iseq, value = "gsgsgd") :
invalid factor level, NAs generated
> df <- data.frame(a = character(0), b=character(0), c=numeric(0), stringsAsFactors=F)
> df[nrow(df)+1,] <- c("d","gsgsgd",4)
> df
a b c
1 d gsgsgd 4
이전 답변에서 제안했듯이 열을 문자로 읽고 rbind
. SQLFetch
( RODBC 라고 가정 합니다 ) 문자 변환을 제어하는 stringsAsFactors
또는 as.is
인수 도 있습니다 . 허용되는 값은 read.table
, 예 as.is=TRUE
또는 일부 열 번호와 같습니다.
유형 불일치, 특히 요인에 대해 동일한 문제가 발생했습니다. 다른 두 개의 호환 가능한 데이터 세트를 함께 붙여야했습니다.
내 솔루션은 두 데이터 프레임의 요소를 "문자"로 변환하는 것입니다. 그런 다음 매력처럼 작동합니다 :-)
convert.factors.to.strings.in.dataframe <- function(dataframe)
{
class.data <- sapply(dataframe, class)
factor.vars <- class.data[class.data == "factor"]
for (colname in names(factor.vars))
{
dataframe[,colname] <- as.character(dataframe[,colname])
}
return (dataframe)
}
실행되는 두 데이터 프레임의 유형을 보려면 (변수 이름 변경) :
cbind("orig"=sapply(allSurveyData, class),
"merge" = sapply(curSurveyDataMerge, class),
"eq"=sapply(allSurveyData, class) == sapply(curSurveyDataMerge, class)
)
데이터 프레임을 만들 때 문자열 열 인수 ( stringsAsFactors=T
) 를 만들거나 문자열 로 유지하도록 선택할 수 있습니다.
For your case, don't make your string columns factors. Keep them as strings, then appending works fine. If you need them to ultimately be factors, do all the insertion and appending first as string, then finally convert them to factor.
If you make the string columns factors and then append rows containing unseen values, you get the error you mentioned on each new unseen factor level and that value gets replaced with NA...
> df <- data.frame(patient=c('Ann','Bob','Carol'), referring_doctor=c('X','Y','X'), stringsAsFactors=T)
patient referring_doctor
1 Ann X
2 Bob Y
3 Carol X
> df <- rbind(df, c('Denise','Z'))
Warning messages:
1: In `[<-.factor`(`*tmp*`, ri, value = "Denise") :
invalid factor level, NA generated
2: In `[<-.factor`(`*tmp*`, ri, value = "Z") :
invalid factor level, NA generated
> df
patient referring_doctor
1 Ann X
2 Bob Y
3 Carol X
4 <NA> <NA>
So don't make your string columns factors. Keep them as strings, then appending works fine:
> df <- data.frame(patient=c('Ann','Bob','Carol'), referring_doctor=c('X','Y','X'), stringsAsFactors=F)
> df <- rbind(df, c('Denise','Z'))
patient referring_doctor
1 Ann X
2 Bob Y
3 Carol X
4 Denise Z
To change the default behavior:
options(stringsAsFactors=F)
To convert individual columns to/from string or factor
df$col <- as.character(df$col)
df$col <- as.factor(df$col)
here's a function to take the common row names of 2 data frames and do an rbind where we basically find the fields that are factors, add the new factors then do the rbind. This should take care of any factor issues:
rbindCommonCols<-function(x, y){
commonColNames = intersect(colnames(x), colnames(y))
x = x[,commonColNames]
y = y[,commonColNames]
colClassesX = sapply(x, class)
colClassesY = sapply(y, class)
classMatch = paste( colClassesX, colClassesY, sep = "-" )
factorColIdx = grep("factor", classMatch)
for(n in factorColIdx){
x[,n] = as.factor(x[,n])
y[,n] = as.factor(y[,n])
}
for(n in factorColIdx){
x[,n] = factor(x[,n], levels = unique(c( levels(x[,n]), levels(y[,n]) )))
y[,n] = factor(y[,n], levels = unique(c( levels(y[,n]), levels(x[,n]) )))
}
res = rbind(x,y)
res
}
'Program Tip' 카테고리의 다른 글
g ++에서 프로필 기반 최적화를 사용하는 방법은 무엇입니까? (0) | 2020.11.15 |
---|---|
Objective-C의 정방향 선언 열거 (0) | 2020.11.15 |
정규식의 복잡성은 무엇입니까? (0) | 2020.11.15 |
MongoDB에서 "id"와 "_id"필드의 차이점 (0) | 2020.11.15 |
소켓 대 SocketChannel (0) | 2020.11.15 |