2016-12-14 12 views
3

とパンダのデータフレーム:Pythonの - 私は、データフレームのこの種を持っているタプル

 A  B  C  D 
0 (a,b) (c,d) (e,f) (g,h) 
1 (a,b) (c,d) (e,f) NaN 
2 (a,b) NaN (e,f) NaN 
3 (a,b) NaN  NaN  NaN 

ので、各セルにタプルがあり、私はそれはそうのようになりようにしたい:

| A  |  B  |  C  |  D 
0 | a | b | c | d | e | f | g | h 
1 | a | b | c | d | e | f | NaN | NaN 
2 | a | b | NaN | NaN | e | f | NaN | NaN 
3 | a | b | NaN | NaN | NaN | NaN | NaN | NaN 

たとえば、列Aには、その内部に2つの列があります。

ありがとうございます。

+0

は、なぜあなたは(たとえば、文字ごとに2つの列を作成する必要はありません。 「A1」と「A2」)? – MMF

答えて

2

あなたはDataFrame.from_recordsstackを使用して、sort_indexによって列と最後のソート列にMultiIndexで、unstackで変更レベルについてswaplevelの形状を変更することができます

stacked = df.stack() 
df1 = pd.DataFrame.from_records(stacked.tolist(), index = stacked.index) 
     .unstack(1) 
     .swaplevel(0, 1, 1) 
     .sort_index(axis=1) 
     .replace({None:np.nan}) 
print (df1) 

    A  B   C   D  
    0 1 0 1 0 1 0 1 
0 a b c d e f g h 
1 a b c d e f NaN NaN 
2 a b NaN NaN e f NaN NaN 
3 a b NaN NaN NaN NaN NaN NaN 

最終が可能に削除されますMultiIndexを作成し、新しい列名を作成します。

stacked = df.stack() 
df1 = pd.DataFrame.from_records(stacked.tolist(), index = stacked.index) 
     .unstack(1) 
     .swaplevel(0, 1, 1) 
     .sort_index(1) 
     .replace({None:np.nan}) 
df1.columns = ['{}{}'.format(col[0], col[1]) for col in df1.columns] 
print (df1) 
    A0 A1 B0 B1 C0 C1 D0 D1 
0 a b c d e f g h 
1 a b c d e f NaN NaN 
2 a b NaN NaN e f NaN NaN 
3 a b NaN NaN NaN NaN NaN NaN 

タイミング:タイミングため

#len (df)=400 

In [220]: %timeit (pir(df)) 
100 loops, best of 3: 3.45 ms per loop 

In [221]: %timeit (jez(df)) 
100 loops, best of 3: 5.17 ms per loop 

In [222]: %timeit (nick(df)) 
1 loop, best of 3: 231 ms per loop 

In [223]: %timeit (df.stack().apply(pd.Series).unstack().swaplevel(0, 1, 1).sort_index(1).replace({None:np.nan})) 
10 loops, best of 3: 152 ms per loop 


#len (df)=4k 

In [216]: %timeit (pir(df)) 
100 loops, best of 3: 16.5 ms per loop 

In [217]: %timeit (jez(df)) 
100 loops, best of 3: 14.8 ms per loop 

In [218]: %timeit (nick(df)) 
1 loop, best of 3: 2.34 s per loop 

In [219]: %timeit (df.stack().apply(pd.Series).unstack().swaplevel(0, 1, 1).sort_index(1).replace({None:np.nan})) 
1 loop, best of 3: 1.53 s per loop 

コード:

df = pd.DataFrame({"A": [('a','b'),('a','b'),('a','b'),('a','b')], 
        'B': [('c','d'),('c','d'), np.nan,np.nan], 
        'C':[('e','f'),('e','f'),('e','f'),np.nan], 
        'D':[('g','h'),np.nan,np.nan,np.nan]}) 

df = pd.concat([df]*1000).reset_index(drop=True) 
print (df) 

def jez(df): 
    stacked = df.stack() 
    return pd.DataFrame.from_records(stacked.tolist(), index = stacked.index).unstack(1).swaplevel(0, 1, 1).sort_index(1).replace({None:np.nan}) 


print (df.stack().apply(pd.Series).unstack().swaplevel(0, 1, 1).sort_index(1).replace({None:np.nan})) 

def nick(df): 
    cols = df.columns.values.tolist() 
    return pd.concat([df[col].apply(pd.Series) for col in cols], axis=1, keys=cols) 

def pir(df): 
    # fillna with (np.nan, np.nan) 
    df_ = df.stack().unstack(fill_value=tuple([np.nan] * 2)) 
    # construct MultiIndex 
    col = pd.MultiIndex.from_product([df.columns, [0, 1]]) 
    # rip off of Nickil's pd.concat but using numpy 
    return pd.DataFrame(np.hstack([np.array(s.values.tolist()) for _, s in df_.iteritems()]), columns=col) 


print (jez(df)) 
print (nick(df)) 
print (pir(df)) 
+0

私は改善に取り組んでいます – piRSquared

1

methon 1
stack + apply

df.stack().apply(pd.Series).unstack().swaplevel(0, 1, 1).sort_index(1) 

enter image description here

方法2

# fillna with (np.nan, np.nan) 
df_ = df.stack().unstack(fill_value=tuple([np.nan] * 2)) 
# construct MultiIndex 
col = pd.MultiIndex.from_product([df.columns, [0, 1]]) 
# rip off of Nickil's pd.concat but using numpy 
pd.DataFrame(
    np.hstack(
     [np.array(s.values.tolist()) \ 
     for _, s in df_.iteritems()] 
    ), columns=col) 

enter image description here

+0

hmmm、私はそれが良いアイデアではないと思う第二のソリューションで列を重複、あなたはどう思いますか? – jezrael

+0

@jezrael私はそれを変更することにしました – piRSquared

+0

大丈夫、私はタイミングにあなたのコードを追加します。 – jezrael

2

スプリットapplyを使用して、個々の要素に、すべてのシリーズのtuples存在。次に、そのような列をすべて列方向に連結し、keys引数を使用して元のDFと同じヘッダーを提供します。

cols = df.columns.values.tolist() 
pd.concat([df[col].apply(pd.Series) for col in cols], axis=1, keys=cols) 

enter image description here

関連する問題