2017-01-20 2 views
1

나는 다음과 같은 데이터 테이블의 데이터 1 (더 라인과 더 유사하지만이 샘플) 한 : 합계 열 값은

item cat1 cat2 cat3 amounts 
1: 1 99 9999 9990  100 
2: 2 12 8199 9990  100 
3: 3 12 8199 9990  100 
4: 4 12 8199 9990  100 
5: 5 12 8199 9990  100 
6: 6 12 8199 9990  100 
7: 7 12 8199 9990  100 
8: 8 12 4129 9990  100 
9: 9 12 8199 9990  100 
10: 10 12 8199 9990  100 

library(data.table) 
data1 <- setDT(structure(list(item = 1:10, cat1 = c("99", "12", "12", "12", 
"12", "12", "12", "12", "12", "12"), cat2 = c("9999", "8199", 
"8199", "8199", "8199", "8199", "8199", "4129", "8199", "8199" 
), cat3 = c("9990", "9990", "9990", "9990", "9990", "9990", "9990", 
"9990", "9990", "9990"), amounts = c("100", "100", "100", "100", 
"100", "100", "100", "100", "100", "100")), .Names = c("item", 
"cat1", "cat2", "cat3", "amounts"), class = c("data.table", "data.frame" 
), row.names = c(NA, -10L))) 

처음에 나는 대한 몇 가지 정보를 얻고 싶었다 cat1, cat2, cat3을 기반으로 한 몇 가지 기준을 충족시키는 라인. 결과 존재와

data1[, .( items = .N, 
      group1 = sum(grepl("^[1-8]{2}$", cat1)), 
      group2 = sum(grepl("^[1-8]9$", cat1)), 
      group3 = sum(grepl("^9[1-8]$", cat1)), 
      group4 = sum(cat1 == "99"))] 

: 그래서 나는이 같은 짓

items group1 group2 group3 group4 
1: 10  9  0  0  1 

이 분석에 포함 된 다른 기준이 많이있었습니다을하지만,이 또한 단지 샘플입니다. 내 요구 사항이 바뀌었고 이제 지정된 모든 그룹에 대해서도 금액을 합산해야합니다. 그래서 두 가지 질문이 :

1) 카운트를 (그래서 기본적인 아이디어는 sum(amounts)grepl("^[1-8]{2}$", cat1))

같은 것 계산하는 일에 유사한 방법으로이 요약 할 데이터 테이블의 방법이 있나요

2) 내가 누락 된 효율적인 방법이 있습니까? 내가 가진 각 기준에 대해 원래의 데이터 세트에 새 열을 추가 한 다음 필터링 된 합을 수행하는 것 외에 제 결과를 얻는 좋은 방법은 생각할 수 없습니다.

내 이상적인 결과는 다음과 같습니다

items group1 group2 group3 group4 total_amounts group1_amounts group2_amounts group3_amounts group4_amounts 
1: 10  9  0  0  1   1000   900    0    0   100 

답변

2

내가 말할 것이다 : 그룹에 대한 전체 매핑 테이블을 (이 상호 배타적 인) :

m = data.table(g = paste0("group", 1:4))[,.(cat1 = as.character(
    if (.GRP==1L) combn(1:8, 2, paste0, collapse = "") else 
    if (.GRP==2L) paste0(1:8, 9) else 
    if (.GRP==3L) paste0(9, 1:8) else 
    if (.GRP==4L) "99" 
)), by=g] 

가 매핑이 있는지 확인 ... 기본 테이블에 변수로

stopifnot(m[duplicated(cat1), .N == 0L]) # mutually exclusive 
stopifnot(data1[!m, on=.(cat1), .N == 0L]) # exhaustive 

추가 그룹 :

,
data1[m, on=.(cat1), g := i.g] 

각 그룹이 요약 그룹에 가입 :

res = data1[.(g = unique(m$g)), on=.(g), .(.N, tot_amt = sum(as.numeric(amounts), na.rm=TRUE)), by=.EACHI] 

#   g N tot_amt 
# 1: group1 9  900 
# 2: group2 0  0 
# 3: group3 0  0 
# 4: group4 1  100 

나는이 출력에 대한 더 유용한 형식입니다 생각하지만, 당신이 정말로 하나의 라인 출력을 원하는 경우 ...

cbind(N = sum(res$N), dcast(res, . ~ g, value.var=c("N","tot_amt")))[, !"."] 

#  N N_group1 N_group2 N_group3 N_group4 tot_amt_group1 tot_amt_group2 tot_amt_group3 tot_amt_group4 
# 1: 10  9  0  0  1   900    0    0   100 

단계는

작동 "가입"어떻게

구문은 x[i, on=cols, j, by=.EACHI]입니다. 여기서 i은 목록 또는 data.table입니다.

  • .()x[...] 일부 인수 내부 list()의 별칭입니다.
  • by=.EACHIi의 행마다 그룹을 의미합니다 (i의 행은 x과 일치하지 않습니다).
  • 일반적으로 jby=에서 결정된 각 그룹에 대해 계산됩니다.

댓글

그룹 열을 때, 나는 방법가 없다, 그것은 후자 이후 data1[grepl(yada), g := 1L][grepl(yada2) & is.na(g), g := 2L][grepl(yada3) & is.na(g), g := 3L]처럼, 대신 정규 표현식에 시리즈를 사용하는 테이블을 만들기 위해 더 나은 것 같아요 중복 된 할당 (cat1이 복수 g에 할당 됨) 또는 부재 중 지정 (cat1g에 할당 됨)을 잡아라.

그룹별로 요약 할 때 data1[, ..., by=g] 대신 data1[.(all_groups), on=.(g), ..., by=.EACHI]을 사용하는 것이 가장 바람직하다고 생각합니다. 이는 후자가 테이블에 나타나지 않는 그룹을 건너 뛰기 때문입니다.

+1

대단히 감사합니다! – User2321