2017-01-10 38 views
7

kendi değerleriyle sütun başlıkları bir grup takas nasıl Aşağıdaki veri çerçevesini vardır:Pandalar

a1 | a2 | a3 | a4 
--------------------- 
Bob | Cat | Dov | Edd 
Cat | Dov | Bob | Edd 
Edd | Cat | Dov | Bob 

ve ben

Bob | Cat | Dov | Edd 
--------------------- 
a1 | a2 | a3 | a4 
a3 | a1 | a2 | a4 
a4 | a2 | a3 | a1 

Not dönüştürmek istediğiniz sütun sayısı benzersiz değerlerin sayısına eşittir ve satırların sayısı ve sırası korunur

cevap

9

1) Gerekli yaklaşım:

Daha hızlı bir uygulama buna göre buna dayalı sütunları dataframe değerlerini sıralamak ve hizalamak olacaktır np.argsort sonra indeksleri elde ediyor.

df.columns[np.argsort(df.values)] 
Out[156]: 
Index([['a1', 'a2', 'a3', 'a4'], ['a3', 'a1', 'a2', 'a4'], 
     ['a4', 'a2', 'a3', 'a1']], 
     dtype='object') 

2) Yavaş genelleştirilmiş yaklaşımın:

pd.DataFrame(df.columns[np.argsort(df.values)], df.index, np.unique(df.values)) 

enter image description here

np.argsort uygulanması bize aradığımız veriyi verirBazı hız/verimlilik pahasına daha genelleştirilmiş yaklaşım, dict veri çerçevesinde bulunan dizeleri/değerleri, ilgili sütun adlarıyla eşleştirdikten sonra apply kullanmak olacaktır.

Elde edilen seriyi list gösterimlerine dönüştürdükten sonra bir veri çerçeve yapıcısı kullanın.

pd.DataFrame(df.apply(lambda s: dict(zip(pd.Series(s), pd.Series(s).index)), 1).tolist()) 

3) hızlı genel yaklaşım:

+ orient='records'df.to_dict gelen sözlük bir listesini elde edildikten sonra, içinde bunların yineleme sırasında, ilişkili oldukları anahtar ve değer çiftleri değiş tokuş etmek için ihtiyaç bir döngü.


pd.DataFrame([{val:key for key, val in d.items()} for d in df.to_dict('r')]) 
Örnek test durumda:

df = df.assign(a5=['Foo', 'Bar', 'Baz']) 

Bu iki yaklaşım üretmek:

enter image description here


@piRSquared DÜZENLEME

genelleştirilmiş çözüm

def nic(df): 
    v = df.values 
    n, m = v.shape 
    u, inv = np.unique(v, return_inverse=1) 
    i = df.index.values 
    c = df.columns.values 
    r = np.empty((n, len(u)), dtype=c.dtype) 
    r[i.repeat(m), inv] = np.tile(c, n) 
    return pd.DataFrame(r, i, u) 

ben merkezli gerçekten hızlı ve yaygın Numpy hazırlamakla piRSquared @ kullanıcıyı teşekkür etmek istiyorum alternatif soln.

+1

için teşekkür ederiz, bunun yalnızca her şeyin düzgün bir şekilde temsil edildiği özel koşullar altında çalıştığını unutmayın. Bu harika bir cevap, sadece işaret ediyorum – piRSquared

+1

Teşekkürler. Sanırım OP, bu mesajın dibinde durumdan bahsetmişti. Aksi takdirde, tüm sütunlar eşit olarak temsil edilmediyse, sanırım bu başarısız olur. –

+0

Bu anlamlı geliyor – piRSquared

5

Yığını ile yeniden şekillendirebilir ve değerlerin ve dizinin değiştirilip kaldırılmasını sağlayabilirsiniz:

df_swap = (df.stack()      # reshape the data frame to long format 
      .reset_index(level = 1)  # set the index(column headers) as a new column 
      .set_index(0, append=True) # set the values as index 
      .unstack(level=1))   # reshape the data frame to wide format 

df_swap.columns = df_swap.columns.get_level_values(1) # drop level 0 in the column index 
df_swap 

enter image description here

+1

'reset_index' bir dataframe döner 'olarak to_frame', gerekli değildir. – IanS

+0

İstenilen yanıt ve açıklama için :) :) – edmondawad

1

numpy + inanmak pandas

v = df.values 
n, m = v.shape 
i = df.index.values 
c = df.columns.values 

# create series with values that were column values 
# create multi index with first level from existing index 
# and second level from flattened existing values 
# then unstack 
pd.Series(
    np.tile(c, n), 
    [i.repeat(m), v.ravel()] 
).unstack() 

    Bob Cat Dov Edd 
0 a1 a2 a3 a4 
1 a3 a1 a2 a4 
2 a4 a2 a3 a1