2017-06-30 93 views
2

這完全是合法的Python:熊貓串除了跨列

In [1]: 'abc' + 'def' 
Out[1]: 'abcdef' 

如果我有一個所有文字熊貓據幀,如下面的例子:

In [2]: df = pd.DataFrame([list('abcd'), list('efgh'), list('ijkl')], 
          columns=['C1','C2','C3','C4']) 
     df.loc[[0,2], ['C2', 'C3']] = np.nan 
     df 
Out[2]:  C1 C2 C3 C4 
     0 a NaN NaN d 
     1 e f g h 
     2 i NaN NaN l 

是否有可能做同樣的與上面的DataFrame的列?例如:

In [3]: df.apply(+, axis=1) # Or 
     df.sum(axis=1) 

請注意,上述兩個語句都不起作用。在循環中使用.str.cat()很容易,但我在尋找更好的東西。


預期成果是:

Out[3]: C 
     0 ad 
     1 efgh 
     2 il 

回答

5

你可以做

df.fillna('').sum(axis=1) 

當然,這是假定你的數據幀只的字符串和NaN組成。

+0

我想我的數據幀是由唯一的字符串和'NaN's的,我希望它是正確的! :-P – Kartik

4

選項1
stack

我想補充它的示範。我們不必接受數據幀的矩形性質,並使用stack。當我們這樣做時,默認情況下,stack下降nan。給我們留下一串字符串和一個pd.MultiIndex。我們可以groupby這個pd.MultiIndex(這曾經是行索引)的第一層和執行求和:

df.stack().groupby(level=0).sum() 

0  ad 
1 efgh 
2  il 
dtype: object 

1選項
,使用屏蔽數組np.ma.masked_array
我被@jezrael動機發布更快的解決方案( - :

pd.Series(
    np.ma.masked_array(
     df.values, 
     df.isnull().values, 
    ).filled('').sum(1), 
    df.index 
) 

0  ad 
1 efgh 
2  il 
dtype: object 

定時

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

%%timeit 
pd.Series(
    np.ma.masked_array(
     df.values, 
     df.isnull().values, 
     fill_value='' 
    ).filled('').sum(1), 
    df.index 
) 

1000 loops, best of 3: 860 µs per loop 

%timeit (pd.Series(df.fillna('').values.sum(axis=1), index=df.index)) 

1000 loops, best of 3: 1.33 ms per loop 
+1

我的朋友總是歡迎替代方法。我們無法保證所有尺寸均適用。 – Kartik

+0

@Kartik我完全同意( - : – piRSquared

2

有點更快的解決方案是通過values轉換爲numpy的數組,然後numpy.sum

#[3000 rows x 4 columns] 
df = pd.concat([df]*1000).reset_index(drop=True) 
#print (df) 

In [49]: %timeit (df.fillna('').sum(axis=1)) 
100 loops, best of 3: 4.08 ms per loop 

In [50]: %timeit (pd.Series(df.fillna('').values.sum(axis=1), index=df.index)) 
1000 loops, best of 3: 1.49 ms per loop 

In [51]: %timeit (pd.Series(np.sum(df.fillna('').values, axis=1), index=df.index)) 
1000 loops, best of 3: 1.5 ms per loop 
+0

嗯,很好的一個。 – jezrael