2014-12-01 3 views
3

중첩 된 사전에 다른 항목을 추가하는 방법에 대해 다른 OP의 question에 응답했으며 세 개의 중첩 된 for 루프 메소드를 세 가지 수준의 사전에 항목을 추가하십시오. 작동하지만, meeeh ... 나는 그것이 더 간결하게 할 수 있다고 확신합니다. 하나의 라이너 (또는 2 개의 라이너)에서 3 레벨 중첩 사전의 스쿼시 및 합계

실제 사용 사례 시나리오를 제공한다 :

:의 나는 많은 사람들이 10 분 간격으로 가게에서 및 를 걸어 어떻게 계산 일부 상점의 입구를 통해 카메라에서 일부 데이터를 가지고 있다고 가정 해 봅시다
data = { 
     "2014/01/01": { 
      "15:00:00" : { 
       "ins": 7, 
       "outs": 5, 
      }, 
      "15:10:00" : { 
       "ins": 24, 
       "outs": 10, 
      }, 
      "15:20:00" : { 
       "ins": 10, 
       "outs": 20, 
      }, 
     }, 
     "2014/01/02": { 
      "15:00:00" : { 
       "ins": 10, 
       "outs": 10, 
      }, 
      "15:10:00" : { 
       "ins": 12, 
       "outs": 5, 
      }, 
      "15:20:00" : { 
       "ins": 5, 
       "outs": 10, 
      }, 
     }, 
} 

나는 그 사전을 함께에 스쿼시을 좋아하고 날짜에 관계없이 특정 시간을 그룹화 아웃을 추가 할 것입니다. " 날짜를 불문하고 각 시간 양동이에 대해 얼마나 많은 사람들이 내 자리에서 나올 수 있었는지 알고 싶습니다."또는 다른 말로 표현합니다. "얼마나 많은 인과 아웃이 있었는지 알고 싶습니다. 각 시간 버킷 시간의 시작 "그 키의 모든 dicts의 인에게아웃를 추가하는 결과가 될 것입니다

하면 data DICT에있는 시간 (첫 데이트를 무시하고있다" 레벨 ") 위에 제공된 샘플 data을 사용하면

"15:00:00": { 
    "ins": 17 # (7 + 10) 
    "outs": 15 # (5 + 10) 
}, 
"15:10:00": { 
    "ins": 36 # (24 + 12) 
    "outs": 15 # (10 + 5) 
}, 
"15:20:00": { 
    "ins": 15 # (10 + 5) 
    "outs": 30 # (20 + 10) 
} 

어떻게 든 방법이 ... (내가 itertools을 통해 추측하고있어,하지만 난이 올바른 사람이 될 것이다 도구 모른다), data로 시작, 결과는 하나의 위 치울의 거기에 라인 (또는 두 개)?

나는
  • summing items in nested dictionary with different keys
  • Sum the nested dictionary values in python
    • 에있는 답변을 조롱했습니다하지만 내가 원하는 것을 얻을하는 방법을 알아낼 수 없습니다. 나도 Counter 개체 목록을 얻습니다. (그리고 나서 나는 그들과 무엇을해야할지 모르겠습니다.) 두 개를 추가하려고하기 때문에 오류가 발생합니다 ...

      저는 실제로 크지 않습니다. deal (3 개의 for 루프는 작업을 완료합니다.)하지만이 코드의 실행 가능성과 코드 단축 방법에 대해 궁금합니다 (itertools은 대략 시간입니다 ...)

      감사합니다. 전진.

    +0

    'sorted'와 ['itertools.groupby'] (https://docs.python.org/2/library/itertools.html#itertools.groupby)의 조합으로 할 수 있다고 생각하지만, 지금 당장 상세한 답변을 남길 시간이 없습니다. –

    +0

    코드는 좋은 한 라이너 목록에 번역 할 수 있어야하지만 좀 길고 지저분하고 기능적으로 다르지는 않습니다. 코드를 게시할까요? – user2782067

    +0

    @ user2782067, 내가 생각할 수있는 가장 좋은 점은 (음 ...'values ​​() '를 사용할 수있을 때'keys()'를 남용하고 있었지만 실제로는 그다지 신경 쓰지는 않는다). 대답은이 질문 (이 답변 : http://stackoverflow.com/a/27217180/289011) – BorrajaX

    답변

    1

    는 예, 그것은 하나의 라이너로 수행 할 수 있습니다. 나는 이것을 두 줄로 나누었고 심지어 그것으로는 읽을 수 없다. 뭔가 수행해야 그것을 의미하지 않는다 수행 할 수 있습니다해서

    flattened = sorted((time,key,count) for day in data.values() for time,counters in day.items() for key,count in counters.items()) 
    {time:{key:sum(datum[2] for datum in counters) for key,counters in itertools.groupby(group, lambda x:x[1])} for time,group in itertools.groupby(flattened, lambda x:x[0])} 
    
    {'15:20:00': {'outs': 30, 'ins': 15}, '15:00:00': {'outs': 15, 'ins': 17}, '15:10:00': {'outs': 15, 'ins': 36}} 
    

    . 나는 가장 명확한 해결책으로 갈 것이고 이것은 그렇지 않다.

    +0

    yawwwzaa ... 예, 동의합니다 ... 생각보다 못 생겼습니다 ** : - D ** – BorrajaX

    1

    당신은 팬더 DataFrames 사용할 수 있습니다 당신이 원하는 조건으로 dataframe (folowings 이전의 질문에 대답) 간단한 NumPy와 합을 수행하는 또 다른 하나를() 만들려면 하나 그것은 2 줄 것 https://stackoverflow.com/a/18162021/764322

    을, 라인 끝에 추가하여 한 줄로 만들 수도 있습니다 (상당히 길지만).

    업데이트 : 코드는 해당되지 않습니다 ...칼럼 1 및 2 ins이다

    # Create data frame 
    >>> table = pd.DataFrame([[c2, d2['ins'], d2['outs']] for d1 in data.values() for c2, d2 in d1.items()]) 
    >>> table 
          0 1 2 
    0 15:20:00 5 10 
    1 15:00:00 10 10 
    2 15:10:00 12 5 
    3 15:20:00 10 20 
    4 15:00:00 7 5 
    5 15:10:00 24 10 
    
    [6 rows x 3 columns] 
    

    outs이다.

    >>> table.groupby(0).sum() 
          1 2 
    0    
    15:00:00 17 15 
    15:10:00 36 15 
    15:20:00 15 30 
    
    +0

    나는 그것을 보겠습니다. 나는 내장 함수를 사용하여 무언가를 기대했다. 답변 해주셔서 감사합니다! – BorrajaX

    +0

    팬더를 사용하는 솔루션으로 편집하여 관심이있는 경우에 대비하십시오. –

    +0

    이것은 확실히 유효하고 흥미 롭습니다. (아마 내가 묻고있는 것을 성취하기위한 올바른 방법 일 것입니다.)하지만 질문의 원래 정신에서 조금 벗어나는 것 같습니다. 분명히 * upvote * (확실히) 가치가 있습니다. – BorrajaX

    2

    이 두 줄보다 조금 더,하지만 :

    from collections import Counter, defaultdict 
    
    flattened = (time for day in data.itervalues() for time in day.iteritems()) 
    sums = defaultdict(lambda: Counter()) 
    
    for time, entries in flattened: 
        sums[time] += Counter(entries) 
    

    주는 :

    In [116]: dict(sums) 
    Out[116]: 
    {'15:00:00': Counter({'ins': 17, 'outs': 15}), 
    '15:10:00': Counter({'ins': 36, 'outs': 15}), 
    '15:20:00': Counter({'outs': 30, 'ins': 15})} 
    
    관련 문제