2016-06-21 4 views
1

R과 새롭게 등장한이 유형의 경우 비교적 새로운 것으로 검색되어 도움이되는 정보를 많이 찾을 수 없습니다.중복 행이있는 다중 데이터 프레임을 병합 R

나는 각각 40,000 - 60,000 개의 행으로 약 150 개의 .csv 파일을 가지고 있으며, 각각에서 3 개의 열을 1 개의 큰 데이터 프레임으로 병합하려고합니다. 각 파일에서 관심있는 3 개의 칼럼 ("id", "name"및 "value")을 추출하고 "id"와 "name"을 큰 데이터 프레임 "MergedData"로 병합하는 작은 스크립트가 있습니다.

file_list <- list.files() 

for (file in file_list){ 

    if(!exists("MergedData")){ 
    MergedData <- read.csv(file, skip=5)[ ,c("id", "name", "value")] 
    colnames(MergedData) <- c("id", "name", file) 
    } 

    else if(exists("MergedData")){ 
    temp_data <- read.csv(file, skip=5)[ ,c("id", "name", "value")] 
    colnames(temp_data) <- c("id", "name", file) 
    MergedData <- merge(MergedData, temp_data, by=c("id", "name"), all=TRUE) 
    rm(temp_data) 
    } 
} 

아니 모든 파일이 있습니다 : 여기 내 코드 (! 난이이 일을 매우 비효율적 인 방법입니다 확신하고 지금은 나와 함께 괜찮아요,하지만 물론 내가 더 나은 옵션 열려있어)입니다 많은 행이 많은 파일에 공통적이긴하지만 같은 수의 행. 포괄적 인 행 목록이 없으므로 MergedData 파일에 아직 존재하지 않는 새 행을 추가하려면 all = TRUE가 포함되었습니다.

내 문제는 : 파일의 대부분은 동일한 "id"및 "name"항목이 있지만 "value"항목이 다른 2-4 개의 행을 포함하고 있습니다. 그래서, 그것들을 병합 할 때 가능한 모든 조합에 대해 행을 추가하게됩니다. 가장 절망적 인 점은 이러한 복제물이 나에게 전혀 관심이 없다는 것입니다. 첫 번째 항목의 값을 가져와 더 이상의 중복 항목을 무시하는 간단한 방법이 있습니까?

감사합니다. 귀하의 의견을 바탕으로, 우리는 다음 각 파일을 스택 및 수

답변

0

은 "오래"를 "폭"형식에서 결과 데이터 프레임을 주조 : 각 파일에서 읽은 후, 위의 코드에서

library(dplyr) 
library(readr) 
library(reshape2) 

df = lapply(file_list, function(file) { 
      dat = read_csv(file) 
      dat$source.file = file 
      return(dat) 
     }) 
df = bind_rows(df) 
df = dcast(df, id + name ~ source.file, value.var="value") 

우리 파일 이름 (또는 수정 된 버전)이 포함 된 새 열 source.file을 추가하십시오. * 그런 다음 dcast을 사용하여 데이터 프레임을 "긴"에서 "와이드"형식으로 캐스팅하여 각 파일의 value에 대한 별도의 열을 만듭니다 방금 작성한 이름 중 하나를 사용하는 새로운 열 source.file.

이 데이터 프레임으로 수행 할 작업에 따라 추가 분석을 위해 긴 형식 (예 : dcast 단계 건너 뛰기)으로 유지하는 것이 더 편리 할 수 ​​있습니다.

부록 : 다루기 Aggregation function missing: defaulting to length 경고. 동일한 id, namesource.file이있는 행이 여러 개있을 때 이런 현상이 발생합니다. 즉, 동일한 셀에 매핑되어야하는 복수의 value이 있으며 이로 인해 집계가 발생합니다. 기본 집계 함수는 length (즉, 셀의 값 개수)입니다. 이 문제를 해결하는 유일한 방법은 (a) 데이터를 긴 형식으로 유지하거나 (b) 다른 집계 함수 (예 : mean)를 사용하거나 (c) counter 열을 추가하여 여러 값으로 사례를 구분합니다. id, namesource.file의 동일한 조합입니다. 우리는 이것들을 아래에 증명합니다.

첫째, 일부 가짜 데이터를 만들 수 : id, namesource.file, 원하는대로 그렇게 dcast 작품의 조합 당

df = data.frame(id=rep(1:2,2), 
       name=rep(c("A","B"), 2), 
       source.file=rep(c("001","002"), each=2), 
       value=11:14) 

df 
id name source.file value 
1 1 A   001 11 
2 2 B   001 12 
3 1 A   002 13 
4 2 B   002 14 
  1. 하나 개의 값입니다.

    id name 001 002 
    1 1 A 11 13 
    2 2 B 12 14 
    
  2. 같은 id, namesource.file에 추가 행을 추가

    dcast(df, id + name ~ source.file, value.var="value") 
    
    . 이제 두 개의 value이 단일 셀에 매핑되므로 dcast을 집계해야합니다. 기본 집계 함수는 값 수의 계수를 제공하는 것입니다.
  3. Aggregation function missing: defaulting to length 
    
        id name 001 002 
    1 1 A 1 2 
    2 2 B 1 1 
    

    df = rbind(df, data.frame(id=1, name="A", source.file="002", value=50)) 
    
    dcast(df, id + name ~ source.file, value.var="value") 
    
    대신, 집계 mean 함수를 사용한다.
    id name 001 002 
    1 1 A 11 31.5 
    2 2 B 12 14.0 
    
  4. 이 같은 id, namesource.file 여러 행이고 dcast의 것을 포함하는 경우를 구별 할 수있는 새로운 counter 열을 추가

    dcast(df, id + name ~ source.file, value.var="value", fun.aggregate=mean) 
    
    . 이렇게하면 셀당 하나의 값으로 돌아 오지만, source.file에 대해 둘 이상의 열을 사용하는 대신에 당신이 볼 수 있듯이

    # Add counter column 
    df = df %>% group_by(id, name, source.file) %>% 
        mutate(counter=1:n()) 
    

    counter 값은 id, namesource.file 단 하나 개의 조합이있을 경우 1의 값을 가지고 있지만, 거기에 하나의 경우에 1과 2의 값이 id, namesource.file (아래 3 행 및 5 행)이있는 두 행

     id name source.file value counter 
    1  1  A   001 11  1 
    2  2  B   001 12  1 
    3  1  A   002 13  1 
    4  2  B   002 14  1 
    5  1  A   002 50  2 
    

    df 
    

    이제 우리는 counterdcast 포함, 그래서 우리는 source.file "002"에 대한 두 개의 열을 얻는다.난 당신이 아마이 고유로 명명 형식을 만들 조정해야합니다 귀하의 파일 이름이 어떻게 생겼는지 모르겠어요 *

    dcast(df, id + name ~ source.file + counter, value.var="value") 
    
    id name 001_1 002_1 002_2 
    1 1 A 11 13 50 
    2 2 B 12 14 NA 
    

파일 식별자. 예를 들어 파일 이름이 "file001.csv", "file002.csv"등의 패턴을 따르는 경우 다음을 수행 할 수 있습니다. dat$source.file = paste0("Value", gsub("file([0-9]{3})\\.csv", "\\1", file).

+0

흠, 나는 이것을 충분히 설명했다고 생각하지 않는다. 나의 최종 목표는 "id", "name"열을 가진 데이터 프레임이고 150 개 파일 각각의 "value"에 대한 150 개 열입니다. 파일에 "id" "name"콤보 값이 있으면 원하는 경우 콤보를 입력하고 NA를 입력하지 않으면됩니다. 내가 그들을 쌓은 다음 중복 된 "id" "name"항목을 제거하면 관련 데이터가 제거되지 않습니까? – JRoon

+0

업데이트 된 코드를보고 내가 찾고있는 코드에 더 가까이 있는지 알려주십시오. – eipi10

+0

닫기입니다. '> df = bind_rows (df)' 경고 메시지 : 1 : rbind_all (x, .id)에서 같지 않은 요소 수준 : 문자로 강제 변환 됨 2 : rbind_all (x, .id)에서 : 동일하지 않은 요소 수준 : 문자로 강제 변환 '> df = dcast (df, id + name ~ source.file, value.var = "value")' 집계 기능이 누락되었습니다. 길이는 기본값으로 설정됩니다. 결과 데이터 프레임은 올바르게 구조화되어 있지만 값은 실제로 값 자체가 아닌 해당 행에 대한 각 .csv 파일의 항목 수입니다. – JRoon

관련 문제