2014-04-21 2 views
3

일반적인 SQL은 "A로 테이블 그룹에서 A를 선택하십시오."이며 일반적인 팬더에서 이것을 복제하고 싶습니다. 데이터가 CSV 파일과 같은 것으로 저장되어 있고 너무 커서 메모리에로드 할 수 없다고 가정합니다. csv로 메모리에 들어갈 수 있다면Pandas GroupBy CSV의 대형 데이터 세트

단순한 2 라이너는 충분 :

data=pandas.read_csv("report.csv") 
mean=data.groupby(data.A).mean() 

는 CSV 메모리로 읽을 수없는 경우 하나를 시도 할 수 있습니다 :

chunks=pandas.read_csv("report.csv",chunksize=whatever) 
cmeans=pandas.concat([chunk.groupby(data.A).mean() for chunk in chunks]) 
badMeans=cmeans.groupby(cmeans.A).mean() 

을 결과 cmeans 것을 제외 테이블에는 A의 각 고유 한 값에 대한 반복 된 항목이 포함되어 있습니다. 하나는 별개의 청크에있는 해당 값의 각 모양에 대한 항목입니다 (read_csv의 chunksize는 그룹화 필드에 대해 아무 것도 모르기 때문에). 결과적으로 최종 badMeans 테이블에 잘못된 대답이 있습니다 ... 가중 평균 평균을 계산해야합니다.

final=pandas.DataFrame({"A":[],"mean":[],"cnt":[]}) 
for chunk in chunks: 
    t=chunk.groupby(chunk.A).sum() 
    c=chunk.groupby(chunk.A).count() 
    cmean=pandas.DataFrame({"tot":t,"cnt":c}).reset_index() 
    joined=pandas.concat(final,cmean) 
    final=joined.groupby(joined.A).sum().reset_indeX() 

mean=final.tot/final.cnt 

내가 뭔가를 놓치고 있습니까 :

그래서 작업 방식은 같은 것 같다? 이것은 미친 듯이 복잡해 보인다 ... 나는 이것을 다루기보다는 CSV를 한 줄씩 처리하는 for 루프를 작성하려고한다. 더 좋은 방법이 있어야합니다.

답변

7

다음과 비슷한 것을 할 수 있다고 생각합니다. 조금 더 간단합니다.

id,val 
A,2 
A,5 
B,4 
A,2 
C,9 
A,7 
B,6 
B,1 
B,2 
C,4 
C,4 
A,6 
A,9 
A,10 
A,11 
C,12 
A,4 
A,4 
B,6 
B,5 
C,7 
C,8 
B,9 
B,10 
B,11 
A,20 

나는 5의 덩어리를 할 수 있습니다 :

chunks = pd.read_csv("foo.csv",chunksize=5) 
pieces = [x.groupby('id')['val'].agg(['sum','count']) for x in chunks] 

agg = pd.concat(pieces).groupby(level=0).sum() 
print agg['sum']/agg['count'] 

id 
A  7.272727 
B  6.000000 
C  7.333333 

비 청크 버전에 비해 : 나는 다음과 같은 데이터를 만들어

df = pd.read_csv('foo.csv') 
print df.groupby('id')['val'].mean() 

id 
A  7.272727 
B  6.000000 
C  7.333333 
+0

감사합니다 확실히 더 나은 ... 전혀 명확하지는 않지만 (그리고 int의 오버플로에 대한 몇 가지 우려가 있습니다.) 바라건대 팬더의 향후 버전이이를 더욱 쉽게 만들어 줄 수 있기를 바랍니다. – user116948

+0

이 문제 참조 : https://github.com/pydata/pandas/issues/3202; 이것은 올바르게하는 것이 사소한 일이 아닙니다. 동기 부여가 된 기여자 만 있습니다! – Jeff

+0

dask가 이제이 문제를 해결합니까? – eleanora