2015-01-10 6 views
10

이벤트 기록이있는 데이터 프레임이 있으며 각 ID 번호의 마지막 이벤트가 해당 ID 번호의 시스템의 현재 값과 일치하는지 확인하여 무결성을 검사하려고합니다. 데이터는 요인으로 코딩됩니다.dplyr의 요인 변수 처리

df <-data.frame(ID=c(1,1,1,1,2,2,2,3,3), 
       current.grade=as.factor(c("Senior","Senior","Senior","Senior", 
             "Junior","Junior","Junior", 
             "Sophomore","Sophomore")), 
       grade.history=as.factor(c("Freshman","Sophomore","Junior","Senior", 
            "Freshman","Sophomore","Junior", 
            "Freshman","Sophomore"))) 

I가 current.grade 대해 그것을 grade.history 마지막 값을 추출하여 확인 dplyr 사용하려는 출력을

> df 
    ID current.grade grade.history 
1 1  Senior  Freshman 
2 1  Senior  Sophomore 
3 1  Senior  Junior 
4 1  Senior  Senior 
5 2  Junior  Freshman 
6 2  Junior  Sophomore 
7 2  Junior  Junior 
8 3  Sophomore  Freshman 
9 3  Sophomore  Sophomore 
> str(df) 
'data.frame': 9 obs. of 3 variables: 
$ ID   : num 1 1 1 1 2 2 2 3 3 
$ current.grade: Factor w/ 3 levels "Junior","Senior",..: 2 2 2 2 1 1 1 3 3 
$ grade.history: Factor w/ 4 levels "Freshman","Junior",..: 1 4 2 3 1 4 2 1 4 

제공 : 다음 장난감 데이터 프레임은 최소한의 예이다

df.summary <- df %>% 
    group_by(ID) %>% 
    summarize(current.grade.last=last(current.grade), 
      grade.history.last=last(grade.history)) 

그러나 dplyr은 인자를 정수로 변환하는 것으로 보이므로 다음을 얻습니다.

> df.summary 
Source: local data frame [3 x 3] 

    ID current.grade.last grade.history.last 
1 1     2     3 
2 2     1     2 
3 3     3     4 
> str(df.summary) 
Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 3 obs. of 3 variables: 
$ ID    : num 1 2 3 
$ current.grade.last: int 2 1 3 
$ grade.history.last: int 3 2 4 

원래 요소의 레벨 집합이 다르기 때문에 값이 일치하지 않습니다. dplyr으로이 작업을 수행하는 올바른 방법은 무엇입니까?

나는 R 버전 3.1.1 및 dplyr 버전을 사용하고 0.3.0.2

+0

데이터 세트를 만들 때'stringsAsFactors = FALSE'을 추가하면 코드가 정상적으로 작동합니다.'? data.frame'을 참조하십시오. 일반적인 이해를 위해 [여기] (http://stackoverflow.com/questions/3418128/how-to-convert-a-factor-to-an-integer-numeric-without-a-loss-of-information)를 참조하십시오. 요인, 또는 [여기에] (http://stackoverflow.com/questions/2851015/convert-data-frame-columns-from-factors-to-characters) –

+0

@ 데이비드 OP (꽤 합리적으로) * 원하는 * 여기서 요인을 사용하십시오. –

+0

@ KonradRudolph, 사실일지도 모릅니다. (배경을 읽지는 않았지만 실제 문제는 직면했습니다), 어떻게 합리적으로 * 합리적으로 정의 할 수 있는지 잘 모르겠습니다. –

답변

0

나는 그것이 "수준"로 정수 코드 세트 속성입니다 R의 factor 개체의 성격에 달려있다 생각 모드 문자. 다음

df.summary <- df %>% 
    group_by(ID) %>% 
    summarize(current.grade.last=last(as.character(current.grade)), 
      grade.history.last=last(as.character(grade.history))) 
+0

예, 요인의 작동 방식을 이해합니다. 가능한 경우 이러한 변수를 요인으로 유지하고 싶습니다. 내 실제 데이터 세트는 꽤 크기 때문에 모든 요인을 문자로 변환 한 다음 요인으로 환원하면 메모리와 계산 측면에서 상당히 비쌉니다. – tcquinn

+0

'last (...)'를'tail (..., 1)'로 바꾸면 어떨까요? – lukeA

+0

예. 'last (...) '대신'tail (..., 1)'을 사용하면 변수를 인수로 유지하는 것처럼 보입니다. 그 좋은 해결 방법입니다. 고맙습니다. 내 생각에 이것이'last()'함수가 의도 한 일종의 일이기 때문에 너무 나쁘다. – tcquinn

3

또 다른 방법이이 경우 신입생에, 자연 순서대로 요소 수준을 넣어, 학년, 주니어, 시니어있다 접근하고, : as.character으로 요인 변수를 랩 : 한 가지 방법은 문제를 극복하기 위해 색인 작성을 위해 which.max 기능을 사용하여 각 ID에 대해 가장 높은 값을 선택하십시오. 이 방법을 사용하면 last 기능을 사용하는 것처럼 열이 각 ID에 대해 최저 등급에서 최고 등급으로 정렬되는지에 대해 걱정할 필요가 없습니다.

library(dplyr) 

df <-data.frame(ID=c(1,1,1,1,2,2,2,3,3), 
       current.grade=as.factor(c("Senior","Senior","Senior","Senior", 
              "Junior","Junior","Junior", 
              "Sophomore","Sophomore")), 
       grade.history=as.factor(c("Freshman","Sophomore","Junior","Senior", 
              "Freshman","Sophomore","Junior", 
              "Freshman","Sophomore"))) 


# Ordered vector of grades 
gradeLookup = c("Freshman", "Sophomore", "Junior", "Senior") 

# Reset the values in the grade columns to the ordering in gradeLookup 
df[,-1] = lapply(df[,-1], function(x) { 
    factor(x, levels=gradeLookup) 
}) 

# For each ID, select the values of current.grade and grade.history at the maximum 
# value of grade.history 
df %>% group_by(ID) %>% 
    summarise(current.grade.last = current.grade[which.max(grade.history)], 
      grade.history.last = grade.history[which.max(grade.history)]) 

    ID current.grade.last grade.history.last 
1 1    Senior    Senior 
2 2    Junior    Junior 
3 3   Sophomore   Sophomore 

업데이트 2 : 당신이 정렬하고 오히려 전체 행보다 열을 기준으로 (오히려 최대 값보다) 마지막 값을 캡처 할 때문에이 시도 :

df %>% group_by(ID) %>% 
    summarise(current.grade.last = current.grade[length(grade.history)], 
      grade.history.last = grade.history[length(grade.history)]) 

END 업데이트를 2

데이터에 연도, 학기 또는 학년과 같은 시간 변수가 포함되어 있습니까? 그렇다면 current.grade을 없애고 가장 최근에 출석 한 날짜에 grade.history의 값을 선택하십시오. 이것은 각 학생의 마지막 학년 수준을 알려줍니다. 예를 들어 (시간 변수가 year라고 가정) :

df %>% group_by(ID) %>% 
    summarise(last.grade = grade.history[which.max(year)]) 

UPDATE 1 : 차라리 레벨 라벨보다, 각 레벨에 대한 숫자 코드를 반환하는 코드를 일으키는 모르겠어요. last 함수의 문제가 아닙니다 (last(df$grade.history) 일 경우이 내용을 볼 수 있습니다). 그러나 타임 스탬프별로 정렬하고 마지막 행을 반환하려는 경우 아래 코드는 레벨 레이블을 유지합니다. sliceID의 각 값 내에서 지정한 행을 반환합니다.이 경우 을 사용하여 마지막 행을 지정하면 ID의 각 값에 대한 전체 행 수가 반환됩니다.

df.summary <- df %>% 
    group_by(ID) %>% 
    slice(n()) 
+0

네, 실제 데이터 세트에는 각 엔트리에 대한 타임 스탬프가 있습니다. 그리고 마지막 타임 스탬프를 사용하여'last()'함수를 적용하기 전에'arrange()'를 사용하여 각 그룹 내를 정렬합니다. , 반드시 학년이나 기타 무엇이든간에 가장 높은 가치를 지닌 것은 아닙니다). 나는 단순화를 위해 장난감 예제에서 그 단계를 떠났다. 가장 최근의 제안은'last()'가 (summary() 또는 group_by()와 반대되는) 범인이라고 가정 할 때 좋은 제안입니다. – tcquinn

+0

[업데이트에 대한 응답] 실제로 slice()는 내 장난감 예제 (고맙습니다!)에서 실제로 작동하지만, 실제 예에서이 연산을 특정 열에 적용하고자합니다 (다른 열에 다른 요약 함수를 적용하고 싶습니다). 'summarize()'와'last()'를 사용하고있었습니다. 인자를 정수로 변환하는 두 함수 중 하나 인 것 같습니다. 다른 제안은? 내가 원하는 컬럼을 꺼내기 위해'select() '를 사용할 수 있다고 가정했습니다. 그리고 나서'slice()'를 적용한 후, 결과를'merge()'를 사용하는 다른 요약 함수의 결과와 다시 합치 겠지만 .......... – tcquinn

+0

두번째 업데이트보기 – eipi10