R 형식이 일치하지 않는 데이터를 정리 하시겠습니까?


16

통계를 수행하기 전에 많은 정리가 필요한 지저분한 설문 조사 데이터를 다루는 경우가 많습니다. Excel에서이 작업을 "수동으로"수행하고, 때로는 Excel 수식을 사용하고, 항목을 하나씩 확인하는 경우가있었습니다. 나는 R에서 스크립트를 작성함으로써 훨씬 더 많은 작업을 시작했다. R에서 스크립트를 작성함으로써 매우 유익했다. 업데이트).

그러나 여전히 효율적으로 처리하는 데 문제가있는 몇 가지 유형의 데이터가 있습니다. 예를 들면 다음과 같습니다.

> d <- data.frame(subject = c(1,2,3,4,5,6,7,8,9,10,11),
+   hours.per.day = c("1", "2 hours", "2 hr", "2hr", "3 hrs", "1-2", "15 min", "30 mins", "a few hours", "1 hr 30 min", "1 hr/week"))
> d
   subject hours.per.day
1        1             1
2        2       2 hours
3        3          2 hr
4        4           2hr
5        5         3 hrs
6        6           1-2
7        7        15 min
8        8       30 mins
9        9   a few hours
10      10   1 hr 30 min
11      11     1 hr/week

hours.per.day특정 활동에 소요되는 하루 평균 시간을 의미하지만 우리가 가진 것은 주제가 쓴 것과 정확히 일치합니다. 모호한 응답으로 수행 할 작업을 결정 hours.per.day2하고 다음과 같이 정리 된 변수 를 원한다고 가정합니다 .

   subject hours.per.day hours.per.day2
1        1             1      1.0000000
2        2       2 hours      2.0000000
3        3          2 hr      2.0000000
4        4           2hr      2.0000000
5        5         3 hrs      3.0000000
6        6           1-2      1.5000000
7        7        15 min      0.2500000
8        8       30 mins      0.5000000
9        9   a few hours      3.0000000
10      10   1 hr 30 min      1.5000000
11      11     1 hr/week      0.1428571

사례의 수가 상당히 많고 (예 : 1000), 피험자가 자신이 좋아하는 것을 자유롭게 쓸 수 있다는 것을 알고 있다고 가정하면, 이것에 접근하는 가장 좋은 방법은 무엇입니까?

답변:


13

gsub ()을 사용하여 내가 아는 문자열을 식별 한 다음 나머지를 직접 수행합니다.

test <- c("15min", "15 min", "Maybe a few hours", 
          "4hr", "4hour", "3.5hr", "3-10", "3-10")
new_var <- rep(NA, length(test))

my_sub <- function(regex, new_var, test){
    t2 <- gsub(regex, "\\1", test)
    identified_vars <- which(test != t2)
    new_var[identified_vars] <- as.double(t2[identified_vars])
    return(new_var)    
}

new_var <- my_sub("([0-9]+)[ ]*min", new_var, test)
new_var <- my_sub("([0-9]+)[ ]*(hour|hr)[s]{0,1}", new_var, test)

손으로 직접 변경 해야하는 작업을 수행하려면 다음과 같이 제안하십시오.

# Which have we not found
by.hand <- which(is.na(new_var))

# View the unique ones not found
unique(test[by.hand])
# Create a list with the ones
my_interpretation <- list("3-10"= 5, "Maybe a few hours"=3)
for(key_string in names(my_interpretation)){
    new_var[test == key_string] <- unlist(my_interpretation[key_string])
}

이것은 다음을 제공합니다.

> new_var
[1] 15.0 15.0  3.0  4.0  4.0  3.5  5.0  5.0

정규식은 약간 까다로울 수 있습니다. 정규식으로 무언가를 할 때마다 몇 가지 간단한 테스트를 실행합니다. 매뉴얼에 대한 정규 표현식. 기본 동작은 다음과 같습니다.

> # Test some regex
> grep("[0-9]", "12")
[1] 1
> grep("[0-9]", "12a")
[1] 1
> grep("[0-9]$", "12a")
integer(0)
> grep("^[0-9]$", "12a")
integer(0)
> grep("^[0-9][0-9]", "12a")
[1] 1
> grep("^[0-9]{1,2}", "12a")
[1] 1
> grep("^[0-9]*", "a")
[1] 1
> grep("^[0-9]+", "a")
integer(0)
> grep("^[0-9]+", "12222a")
[1] 1
> grep("^(yes|no)$", "yes")
[1] 1
> grep("^(yes|no)$", "no")
[1] 1
> grep("^(yes|no)$", "(yes|no)")
integer(0)
> # Test some gsub, the \\1 matches default or the found text within the ()
> gsub("^(yes|maybe) and no$", "\\1", "yes and no")
[1] "yes"

답변 Max에 감사드립니다. 나는 정규 표현식에 익숙하지 않으므로 이에 대해 알아야합니다. 나머지는 손으로하는 방법에 대해 간단히 설명해 주시겠습니까? 단지 같은 것을하는 것보다 더 나은 방법이 new_var[by.hand] <- c(2, 1, ...)by.hand있는 TRUE손에 의해 수행되는 경우에는?
mark999

@ mark999 : 몇 가지 예와 손으로 직접 할 수있는 방법에 대한 제안을 추가했습니다.
Max Gordon

1
정규 표현식은 모든 종류의 데이터 조작에 매우 중요합니다. OP와 같이 데이터 정리 또는 파일, HTML 등에서 데이터 추출. (올바른 HTML의 경우 XML데이터 추출을 돕는 라이브러리가 있습니다. HTML 형식이 잘못된 경우 작동하지 않습니다.)
Wayne

6

@Max의 제안은 좋은 것입니다. 일반적인 시간 관련 단어 / 약어뿐만 아니라 숫자를 인식하는 알고리즘을 작성하면 대부분의 방법을 사용할 수 있습니다. 이것은 아름다운 코드는 아니지만 작동하지만 문제가 발생할 때 시간이 지남에 따라 코드를 향상시킬 수 있습니다.

그러나보다 강력하고 초기에는 시간이 많이 걸리는 접근 방식을 위해 "자연 언어 시간 문자열을 구문 분석"하는 인터넷 검색을 사용해보십시오. 흥미로운 결과는이 Open time API , 좋은 파이썬 모듈Stack Overflow 에서 이와 같은 많은 독일 스레드 중 하나입니다 .

기본적으로 자연어 구문 분석은 일반적인 문제이므로 R 이외의 언어로 솔루션을 찾아야합니다. R을 사용하여 액세스 할 수있는 다른 언어로 도구를 만들거나 최소한 자체 알고리즘에 대한 좋은 아이디어를 얻을 수 있습니다.


4

그런 식으로 충분히 길면 정규 표현식 및 변환 규칙 목록을 원하고 새 값을 다른 열로 가져 가려고합니다 (따라서 항상 원시 데이터를 다시로드하지 않고 두 번 확인할 수 있습니다) ; RE는 모든 데이터가 변환되거나 모든 규칙이 소진 될 때까지 지금까지 변환되지 않은 데이터에 적용됩니다. 아직 변환되지 않은 행을 나타내는 논리 값 목록을 유지하는 것이 가장 좋습니다.

그러한 규칙은 당연히 명백하며 아마도 80-90 %의 사례를 처리 할 것이지만 문제는 항상 당신이 알지 못하는 것들이있을 것이라는 점입니다 (사람들은 매우 독창적입니다).

그런 다음 아직 아직 변환되지 않은 명백한 규칙 목록 값의 원본을 한 번에 하나씩 제공하여 정규 표현식을 만들 수있는 스크립트가 필요합니다 (예 : ) 해당 사례를 파악하고 새로운 에 맞는 변형을 제공합니다.이 사례는 원래 목록에 추가되고 아직 제시되지 않은 사례가 있는지 확인하기 전에 원본 벡터의 아직 변환되지 않은 행에 적용됩니다. .

건너 뛰는 옵션을 갖는 것이 합리적 일 수도 있습니다사례 있으므로 (더 쉬운 사례로 진행할 수 있도록) 매우 어려운 사례를 끝까지 고칠 수 있습니다.

최악의 경우, 손으로 몇 가지 작업을 수행합니다.

그런 다음 생성 한 전체 규칙 목록을 유지하여 데이터가 커지거나 새로운 유사한 데이터 세트가 나타날 때 다시 적용 할 수 있습니다.

원격으로 모범 사례에 접근하고 있는지는 알지 못하지만 (더 공식적인 것이 필요할 것이라고 생각합니다) 대량의 데이터를 신속하게 처리한다는 측면에서 가치가있을 수 있습니다.


답변 주셔서 감사합니다, 글렌 매우 매력적입니다. 아직 변환되지 않은 값을 한 번에 하나씩 표시하는 것이 큰 장점이라고 생각합니까? 단, 모든 값을 표시하고 해당 출력을 보는 것과는 반대입니다. 한 번에 하나씩 발표하는 것과 같은 일을 한 적이 없습니다.
mark999

1
@ mark999, 나는 한 번에 하나씩 프레젠테이션의 장단점이 있다고 생각합니다. cat ()을 사용하여 모호한 시간을 표시하고 scan ()을 사용하여 해당 시간의 해석을 쉽게 구현할 수 있다는 장점이 있습니다. 단점은 한 줄의 정규 표현식 코드로 일괄 수정할 수있는 많은 항목의 큰 그림을 놓칠 수 있다는 것입니다. 당신이 얻고 싶은 것에 대해 생각할 수도 있습니다.이 문제를 해결하고 싶다면 손으로하십시오. R에 대해 더 배우려면 솔루션을 코딩하십시오.
Ash

답장이 없기 때문에 죄송합니다. Ash의 의견에 크게 동의합니다
Glen_b-복지국 Monica

4

R 일부 포함 표준 그것의 데이터 세정에 사용될 수있는 데이터 조작 기능, 베이스 패키지 ( gsub, transform예컨대, 등)뿐만 아니라 다양한 외부 패키지 stringr , 모양 변경 , reshape2plyr를 . 예를 들면 이러한 패키지에 대한 사용의 모범 사례와 그 기능은 다음 종이에 설명되어 있습니다 http://vita.had.co.nz/papers/tidy-data.pdf .

또한 R은 데이터 정리 및 변환에 특별히 초점맞춘 일부 패키지를 제공합니다 .

에 대한 포괄적이고 일관성있는 접근 청소 데이터 예와의 사용을 포함하여 R에, editrulesdeducorrect 패키지뿐만 아니라 설명 워크 플로우 ( 워크 R에 청소 데이터)를, 내가보기 엔 추천하는 다음과 같은 논문에서 제시 : HTTP : //cran.r-project.org/doc/contrib/de_Jonge+van_der_Loo-Introduction_to_data_cleaning_with_R.pdf .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.