2016-02-03 23 views
5

創造出很多新列我有一個的大數據幀df(約100列,約7百萬行),我需要創建〜50個新變量/列這是當前變量的簡單轉換。繼續進行的一種方式是與許多.apply語句(我只是用transform*爲簡單的轉換,如max或平方的佔位符):大多數Python的方式對大熊貓

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

另一種方法是首先建立一個字典

transform_dict = { 
'new_var1' : lambda row : transform1(row), 
..., 
'new_var50' : lambda row : transform50(row) 
} 

然後寫一個.apply.concat組合:

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) 

我■一個方法優於其它,無論是在它是如何「Python化」是,或效率,可擴展性,靈活性?

+0

我期望第二形式是更有效,因爲第一種方法被迭代遞增這將意味着的存儲器和數據複製許多重新分配作爲DF生長 – EdChum

+0

除了使用df:'申請(拉姆達行:transform1( row))'只是寫'a​​pply(transform1)'的較慢方法。 – DSM

回答

2

與開始:

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

添加單個列:

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 

似乎比使用pd.concat相當多的有效的 - 大概是因爲有一個遍歷涉及的DataFramerows。所以,這種差異會變得更糟的DataFrame變長:

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,但大小爲100K×100,並與第一分配NaN的一種塊,並將它加到了一種新的方法實驗數據幀。然後,它使用iloc對每列執行計算。

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