이런 경우에 좋은 접근법은 SQL을 복잡하고 이해하기 힘들고 유지하기가 어려운 시점으로 밀어 넣는 것이 아닙니다. SQL을 통해 편리하게 수행 할 수있는 작업을 수행하고 쿼리 결과를 Python으로 처리 할 수 있습니다.
여기에 필자가 작성한 간단한 크로스 탭 생성기의 축소판 버전이 있습니다. 정식 버전은 행/열/총합을 제공합니다.
"group by"이 내장되어 있음을 알 수 있습니다. 원래의 사용 사례는 Python과 xlrd를 사용하여 Excel 파일에서 얻은 데이터를 요약하기위한 것입니다.
사용자가 제공하는 row_key
및 col_key
은 예제와 같이 문자열 일 필요는 없습니다. 튜플 (예 : 귀하의 경우에 (year, week)
- 또는 정수일 수 있습니다. 문자열 열 이름과 정수 정렬 키의 매핑이 있습니다.
import sys
class CrossTab(object):
def __init__(
self,
missing=0, # what to return for an empty cell. Alternatives: '', 0.0, None, 'NULL'
):
self.missing = missing
self.col_key_set = set()
self.cell_dict = {}
self.headings_OK = False
def add_item(self, row_key, col_key, value):
self.col_key_set.add(col_key)
try:
self.cell_dict[row_key][col_key] += value
except KeyError:
try:
self.cell_dict[row_key][col_key] = value
except KeyError:
self.cell_dict[row_key] = {col_key: value}
def _process_headings(self):
if self.headings_OK:
return
self.row_headings = list(sorted(self.cell_dict.iterkeys()))
self.col_headings = list(sorted(self.col_key_set))
self.headings_OK = True
def get_col_headings(self):
self._process_headings()
return self.col_headings
def generate_row_info(self):
self._process_headings()
for row_key in self.row_headings:
row_dict = self.cell_dict[row_key]
row_vals = [row_dict.get(col_key, self.missing) for col_key in self.col_headings]
yield row_key, row_vals
def dump(self, f=None, header=None, footer='',):
if f is None:
f = sys.stdout
alist = self.__dict__.items()
alist.sort()
if header is not None:
print >> f, header
for attr, value in alist:
print >> f, "%s: %r" % (attr, value)
if footer is not None:
print >> f, footer
if __name__ == "__main__":
data = [
['Rob', 'Morn', 240],
['Rob', 'Aft', 300],
['Joe', 'Morn', 70],
['Joe', 'Aft', 80],
['Jill', 'Morn', 100],
['Jill', 'Aft', 150],
['Rob', 'Aft', 40],
['Rob', 'aft', 5],
['Dozy', 'Aft', 1],
# Dozy doesn't show up till lunch-time
['Nemo', 'never', -1],
]
NAME, TIME, AMOUNT = range(3)
xlate_time = {'morn': "AM", "aft": "PM"}
print
ctab = CrossTab(missing=None,)
# ctab.dump(header='=== after init ===')
for s in data:
ctab.add_item(
row_key=s[NAME],
col_key= xlate_time.get(s[TIME].lower(), "XXXX"),
value=s[AMOUNT])
# ctab.dump(header='=== after add_item ===')
print ctab.get_col_headings()
# ctab.dump(header='=== after get_col_headings ===')
for x in ctab.generate_row_info():
print x
출력 :
['AM', 'PM', 'XXXX']
('Dozy', [None, 1, None])
('Jill', [100, 150, None])
('Joe', [70, 80, None])
('Nemo', [None, None, -1])
('Rob', [240, 345, None])
@yorksranter : 답변을 upvote하고 답변을 수락 하시겠습니까? –
나는 명성 점수가 15 점이 아니다. – user106514
@yorkstranter : 담당자가 더 높을 때 다시 방문 할 수있는 코드가 마음에 들면 괜찮습니다 .- –