2016-06-10 3 views
3

두 개의 서로 관련이없는 시리즈의 조합 인 Dataframe을 만들려고합니다.두 개의 관련없는 시리즈에서 DataFrame을 만드는 가장 효율적인 방법은 무엇입니까?

우리는 두 dataframes 걸릴 경우

A = ['a','b','c'] 
B = [1,2,3,4] 

dfA = pd.DataFrame(A) 
dfB = pd.DataFrame(B) 

내가이 출력을 찾고 있어요 :

A B 
0 a 1 
1 a 2 
2 a 3 
3 a 4 
4 b 1 
5 b 2 
6 b 3 
7 b 4 
8 c 1 
9 c 2 
10 c 3 
11 c 4 

한 가지 방법은 direclty 목록에 루프를 가지고 있고 DataFrame을 만들 수 있지만, 거기는해야합니다 더 나은 방법이 되십시오. 나는 판다 문서에서 뭔가를 놓치고 있다고 확신한다.

result = [] 
for i in A: 
    for j in B: 
     result.append([i,j]) 

result_DF = pd.DataFrame(result,columns=['A','B']) 

가 궁극적으로 내가 결합 개월 UUID 찾고 있어요, 내가 작업 뭔가를하지만 계산하는 나이 소요 인덱스에 너무 많이 의존하고있다. 일반적인 해결책은 분명히 더 나은 것 :

from datetime import datetime 

start = datetime(year=2016,month=1,day=1) 
end = datetime(year=2016,month=4,day=1) 
months = pd.DatetimeIndex(start=start,end=end,freq="MS") 
benefit = pd.DataFrame(index=months) 

A = [UUID('d48259a6-80b5-43ca-906c-8405ab40f9a8'), 
    UUID('873a65d7-582c-470e-88b6-0d02df078c04'), 
    UUID('624c32a6-9998-49f4-92b6-70e712355073'), 
    UUID('7207ab0c-3c7f-477e-b5bc-fbb8059c1dec')] 
dfA = pd.DataFrame(A) 

result = pd.DataFrame(columns=['A','month']) 
for i in dfA.index: 
    newdf = pd.DataFrame(index=benefit.index) 
    newdf['A'] = dfA.iloc[i,0] 
    newdf['month'] = newdf.index 
    result = pd.concat([result,newdf]) 
result 

답변

3

사용할 수 np.meshgrid :

0,123,157 :

pd.DataFrame(np.array(np.meshgrid(dfA, dfB,)).T.reshape(-1, 2)) 

    0 1 
0 a 1 
1 a 2 
2 a 3 
3 a 4 
4 b 1 
5 b 2 
6 b 3 
7 b 4 
8 c 1 
9 c 2 
10 c 3 
11 c 4 

각각 DataFrame 길이 300의 객체와 400에 대략 ~2000x 속도 향상을 얻을 수

np.meshgrid :

%%timeit 
pd.DataFrame(np.array(np.meshgrid(dfA, dfB,)).T.reshape(-1, 2)) 
100 loops, best of 3: 8.45 ms per loop 

cross 대 :

%timeit cross(dfA, dfB) 
1 loop, best of 3: 16.3 s per loop 

난 당신이 할 수 정확하게 예제를 이해 그래서 경우 :

A = ['a', 'b', 'c'] 
dfA = pd.DataFrame(A) 

start = datetime(year=2016, month=1, day=1) 
end = datetime(year=2016, month=4, day=1) 
months = pd.DatetimeIndex(start=start, end=end, freq="MS") 
dfB = pd.DataFrame(months.month) 

pd.DataFrame(np.array(np.meshgrid(dfA, dfB,)).T.reshape(-1, 2)) 

도 얻을 수 있습니다 :

0 1 
0 a 1 
1 a 2 
2 a 3 
3 a 4 
4 b 1 
5 b 2 
6 b 3 
7 b 4 
8 c 1 
9 c 2 
10 c 3 
11 c 4 
+0

매우 빠르지 만 np 배열에 맞는 데이터 유형에서만 작동합니다. 내가 UUID로 시도하면 'TypeError : 지원되지 않는 피연산자 유형'이됩니다. – ludofet

+0

'dtype'은 무엇을보고 있습니까? – Stefan

+0

업데이트 된 답변보기, 내가 오타를 오해 한 경우 알려주십시오. – Stefan

0

한 라이너 방법

pd.DataFrame(0, A, B).stack().index.to_series().apply(pd.Series).reset_index(drop=True) 

또는 : dataframes에서

pd.MultiIndex.from_product([A, B]).to_series().apply(pd.Series).reset_index(drop=True) 

이 정보를 가정하면 첫 번째 열에입니다.

pd.MultiIndex.from_product([dfA.iloc[:, 0], dfB.iloc[:, 0]]).to_series().apply(pd.Series).reset_index(drop=True) 

기능화 :

def cross(df1, df2): 
    s1 = df1.iloc[:, 0] 
    s2 = df2.iloc[:, 0] 
    midx = pd.MultiIndex.from_product([s1, s2]) 
    df = midx.to_series().apply(pd.Series).reset_index(drop=True) 
    df.columns = [s1.name, s2.name if s1.name != s2.name else 1] 
    return df 

print cross(dfA, dfB) 

    0 1 
0 a 1 
1 a 2 
2 a 3 
3 a 4 
4 b 1 
5 b 2 
6 b 3 
7 b 4 
8 c 1 
9 c 2 
10 c 3 
11 c 4 
+0

그건 내가 저장하게 될 좋은 라이너이지만 여전히 목록으로 받아 들여지고 DataFrame은 입력으로 받아 들여지지 않는다. – ludofet

+0

'dfA'와'dfB'의 사용법을 설명하기 위해 편집 됨 – piRSquared

+0

Thanks! 간단한 예제에서 성능 측면을 살펴보면 데이터 프레임을 결합하는 것이 루프 및 목록을 사용하는 것보다 10 배 더 느린 것 같습니다. 나는 그런 작은 주제에서 예상된다. – ludofet

2

또는

a = [1,2,3] 
b = ['a','b','c'] 
x,y = zip(*[i for i in zip(np.tile(a,len(a)),np.tile(b,len(a)))]) 
pd.DataFrame({'x':x,'y':y}) 

출력 :

x y 
0 1 a 
1 2 b 
2 3 c 
3 1 a 
4 2 b 
5 3 c 
6 1 a 
7 2 b 
8 3 c 

%%timeit 
1000 loops, best of 3: 559 µs per loop 

편집 : 당신은 실제로 np.tile 필요하지 않습니다.np.meshgrid으로 매우 효율적

from itertools import product 

result = pd.DataFrame(list(product(dfA.iloc[:,0], dfB.iloc[:,0]))) 

하지,하지만 다른 솔루션보다 더 효율적입니다 : 간단한 이해는 itertools.product를 사용

x,y = zip(*[(i,j) for i in a for j in b]) 
2

할 것입니다.

관련 문제