2016-02-03 20 views
5

Geniş bir veri çerçevem ​​var df (~ 100 sütun ve ~ 7 milyon satır) ve mevcut değişkenlerin basit dönüştürmeleri olan ~ 50 yeni değişken/sütun oluşturmam gerekiyor. Devam etmenin bir yolu (sadece basit dönüşümler böyle max olarak veya kare alma için yer tutucu olarak transform* kullanıyorum) birçok .apply ifadelerle olacaktır:Çoğu Pythonic Yolu Pandalarda Çok Sayıda Yeni Sütun Yaratma

df['new_var1'] = df['old_var1'].apply(lambda x : transform1(x)) 
... 
df['new_var50'] = df['old_var50'].apply(lambda x : transform50(x)) 

başka yolu da öncelikle bir sözlük

transform_dict = { 
'new_var1' : lambda row : transform1(row), 
..., 
'new_var50' : lambda row : transform50(row) 
} 
oluşturmak olacaktır

ve sonra .concat ile kombine birini .apply yazın:

df = pd.concat([df, 
    df.apply(lambda r: pd.Series({var : transform_dict[var](r) for var in transform_dict.keys()}), axis=1)], axis=1) 

ben diğeri üzerinde ne “Pythonic”, ya da verimlilik, ölçeklenebilirlik, esneklik gibi bir tercih edilir?

+0

İlk yöntem, yinelemeli df yana – EdChum

+0

büyüdükçe bellek ve veri kopyalama birçok tahsis edilecek anlamına gelecektir df artırma gibi ikinci bir şekilde daha verimli olması beklenebilir transform1 (row)) 'yazmak için daha yavaş bir yoldur (apply1). – DSM

cevap

2

ile başlayan: Ekleme

df = pd.DataFrame(np.random.random((1000, 100))) 

bireysel sütunlar:

def cols_via_apply(df): 
    for i in range(100, 150): 
     df[i] = df[i-100].apply(lambda x: x * i) 
    return df 

%timeit cols_via_apply(df) 

10 loops, best of 3: 29.6 ms per loop 

<class 'pandas.core.frame.DataFrame'> 
Int64Index: 1000 entries, 0 to 999 
Columns: 150 entries, 0 to 149 
dtypes: float64(150) 
memory usage: 1.2 MB 
None 

biraz daha verimli pd.concat kullanmaktan daha görünüyor - muhtemelen katılan DataFrame ait rows üzerinde bir döngü var, çünkü. DataFrame alır gibi Yani bu fark daha da kötüye gidecek artık:

def cols_via_concat(df): 
    df = pd.concat([df, df.apply(lambda row: pd.Series({i : i * row[i-100] for i in range(100, 150)}), axis=1)]) 
    return df 


%timeit cols_via_concat(df) 

1 loops, best of 3: 450 ms per loop 

<class 'pandas.core.frame.DataFrame'> 
Int64Index: 1000 entries, 0 to 999 
Columns: 150 entries, 0 to 149 
dtypes: float64(150) 
memory usage: 1.2 MB 
None 
2

@Stefan ait ama 100k x 100 boyutunda ve ilk NaN'ler alanı ayıran ve onu birleştirir yeni bir yöntem ile deney devam veri çerçevesi. Daha sonra her sütun üzerinde hesaplamalar yapmak için iloc kullanır. (Lambda satır `geçerlidir:

def cols_via_iloc(df): 
    df = pd.concat([df, pd.DataFrame(np.tile(np.nan, [len(df), 50]))], axis=1) 
    for i in range(100, 150): 
     df.iloc[:, i] = i * df.iloc[:, i - 100] 

def cols_via_apply(df): 
    for i in range(100, 150): 
     df[i] = df[i-100].apply(lambda x: x * i) 
    return df 

def cols_via_concat(df): 
    df = pd.concat([df, df.apply(lambda row: pd.Series({i : i * row[i - 100] 
                 for i in range(100, 150)}), axis=1)]) 
    return df 

>>> %%timeit df = pd.DataFrame(np.random.randn(100000, 100)) 
    cols_via_iloc(df) 
1 loops, best of 3: 540 ms per loop 

>>> %%timeit df = pd.DataFrame(np.random.randn(100000, 100)) 
    cols_via_apply(df) 
1 loops, best of 3: 2.91 s per loop 

>>> %%timeit df = pd.DataFrame(np.random.randn(100000, 100)) 
    cols_via_concat(df) 
1 loops, best of 3: 55.8 s per loop 
İlgili konular