2017-11-26 46 views
13

मैं है एक dataframe कि इस तरह दिखता है:कुशल तरीका

from random import randint 
import pandas as pd 

df = pd.DataFrame({"ID": ["a", "b", "c", "d", "e", "f", "g"], 
        "Size": [randint(0,9) for i in range(0,7)]}) 

df 

    ID Size 
0 a  4 
1 b  3 
2 c  0 
3 d  2 
4 e  9 
5 f  5 
6 g  3 

और क्या मैं प्राप्त करने के लिए चाहते हैं यह (एक मैट्रिक्स हो सकता है के रूप में अच्छी तरह से) है:

sums_df 

     a  b c  d  e  f  g 
a 8.0 7.0 4.0 6.0 13.0 9.0 7.0 
b 7.0 6.0 3.0 5.0 12.0 8.0 6.0 
c 4.0 3.0 0.0 2.0 9.0 5.0 3.0 
d 6.0 5.0 2.0 4.0 11.0 7.0 5.0 
e 13.0 12.0 9.0 11.0 18.0 14.0 12.0 
f 9.0 8.0 5.0 7.0 14.0 10.0 8.0 
g 7.0 6.0 3.0 5.0 12.0 8.0 6.0 

ID में सभी संभावित जोड़े के लिए Size मानों का योग है।

अभी के लिए मैं इस सरल लेकिन unefficient कोड है:

sums_df = pd.DataFrame() 

for i in range(len(df)): 
    for j in range(len(df)): 
     sums_df.loc[i,j] = df.Size[i] + df.Size[j] 

sums_df.index = list(df.ID) 
sums_df.columns = list(df.ID) 

यह इस तरह छोटे उदाहरण के लिए ठीक काम करता है, लेकिन मेरी वास्तविक डेटा के लिए यह बहुत लंबा हो जाता है और मैं इसे नेस्टेड से बचने के लिए संभव है यकीन for loops। क्या आप ऐसा करने के बेहतर तरीके के बारे में सोच सकते हैं?

किसी भी मदद के लिए धन्यवाद!

+2

बस उत्सुक: क्यों आप इसे ज़रूरत है? –

+0

मेरे पास एक और डेटाफ्रेम है जिसे मैं नेटवर्कएक्स के साथ एक आसन्न मैट्रिक्स के रूप में उपयोग कर रहा हूं (चलिए इसे डीएफ 1 कहते हैं), और मैं df1 तत्व-वार को dums2 प्राप्त करने के लिए sums_df द्वारा "विभाजित" करना चाहता हूं। डीएफ 1 में आईडी के बीच सामान्य तत्वों की संख्या शामिल है, लेकिन मेरे पास प्रत्येक आईडी में तत्वों की संख्या भी है (यहां आकार, और आईडी वास्तव में समूहों की आईडी हैं)। इस तरह मैं डीएफ 2 के साथ उपयोग किए जाने वाले वजन डीएफ 1 का उपयोग आसन्न मैट्रिक्स के रूप में सामान्य तत्वों की गणना के बजाय सामान्य तत्वों के शेयर हैं। मुझे उम्मीद है कि यह काफी स्पष्ट है! – atonnerre

उत्तर

22

उपयोग np.add.outer():

In [65]: pd.DataFrame(np.add.outer(df['Size'], df['Size']), 
         columns=df['ID'].values, 
         index=df['ID'].values) 
Out[65]: 
    a b c d e f g 
a 8 7 4 6 13 9 7 
b 7 6 3 5 12 8 6 
c 4 3 0 2 9 5 3 
d 6 5 2 4 11 7 5 
e 13 12 9 11 18 14 12 
f 9 8 5 7 14 10 8 
g 7 6 3 5 12 8 6 

अद्यतन: स्मृति की बचत (पांडा मल्टी सूचकांक) दृष्टिकोण (नोट: इस दृष्टिकोण में बहुत धीमी है, पिछली बार की तुलना):

In [33]: r = pd.DataFrame(np.array(list(combinations(df['Size'], 2))).sum(axis=1), 
    ...:     index=pd.MultiIndex.from_tuples(list(combinations(df['ID'], 2))), 
    ...:     columns=['TotalSize'] 
    ...:) 

In [34]: r 
Out[34]: 
    TotalSize 
a b   7 
    c   4 
    d   6 
    e   13 
    f   9 
    g   7 
b c   3 
    d   5 
    e   12 
    f   8 
    g   6 
c d   2 
    e   9 
    f   5 
    g   3 
d e   11 
    f   7 
    g   5 
e f   14 
    g   12 
f g   8 

इसे निम्नानुसार पहुंचा जा सकता है:

In [41]: r.loc[('a','b')] 
Out[41]: 
TotalSize 7 
Name: (a, b), dtype: int32 

In [42]: r.loc[('a','b'), 'TotalSize'] 
Out[42]: 7 

In [44]: r.loc[[('a','b'), ('c','d')], 'TotalSize'] 
Out[44]: 
a b 7 
c d 2 
Name: TotalSize, dtype: int32 

In [43]: r.at[('a','b'), 'TotalSize'] 
Out[43]: 7 

मेमोरी उपयोग तुलना (DF आकार: 7000x3):

In [65]: df = pd.concat([df] * 1000, ignore_index=True) 

In [66]: df.shape 
Out[66]: (7000, 2) 

In [67]: r1 = pd.DataFrame(np.add.outer(df['Size'], df['Size']), 
    ...:      columns=df['ID'].values, 
    ...:      index=df['ID'].values) 
    ...: 

In [68]: r2 = pd.DataFrame(np.array(list(combinations(df['Size'], 2))).sum(axis=1), 
    ...:     index=pd.MultiIndex.from_tuples(list(combinations(df['ID'], 2))), 
    ...:     columns=['TotalSize']) 
    ...: 

In [69]: r1.memory_usage().sum()/r2.memory_usage().sum() 
Out[69]: 2.6685407829018244 

स्पीड तुलना (DF आकार: 7000x3):

In [70]: %%timeit 
    ...: r1 = pd.DataFrame(np.add.outer(df['Size'], df['Size']), 
    ...:      columns=df['ID'].values, 
    ...:      index=df['ID'].values) 
    ...: 
180 ms ± 2.99 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) 

In [71]: %%timeit 
    ...: r2 = pd.DataFrame(np.array(list(combinations(df['Size'], 2))).sum(axis=1), 
    ...:     index=pd.MultiIndex.from_tuples(list(combinations(df['ID'], 2))), 
    ...:     columns=['TotalSize']) 
    ...: 
17 s ± 325 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 
+0

वही है जो मैं खोज रहा था, और यह वास्तव में बेहद तेज़ है। आपका बहुत बहुत धन्यवाद! – atonnerre

+1

@atonnerre काफी बोलते हुए, यह कितना तेज़ हो रहा है? यह 10% लाभ या 10x लाभ की तरह है? – Nat

+3

क्या परिणाम के समरूपता का लाभ उठाने का कोई तरीका है (या तो दोनों: लगभग आधा तक रनटाइम को कम करने के लिए, लगभग आधे तक भंडारण को कम करने के लिए)? –

11

उपयोग Numpy का प्रसारण

size = df.Size.values 
ids = df.ID.values 

pd.DataFrame(
    size[:, None] + size, 
    ids, ids 
) 

    a b c d e f g 
a 8 7 4 6 13 9 7 
b 7 6 3 5 12 8 6 
c 4 3 0 2 9 5 3 
d 6 5 2 4 11 7 5 
e 13 12 9 11 18 14 12 
f 9 8 5 7 14 10 8 
g 7 6 3 5 12 8 6 
9

या .values और .values.T की तरह कुछ

df1=df.set_index('ID') 
df1.values+df1.values.T 
Out[626]: 
array([[ 8, 7, 4, 6, 13, 9, 7], 
     [ 7, 6, 3, 5, 12, 8, 6], 
     [ 4, 3, 0, 2, 9, 5, 3], 
     [ 6, 5, 2, 4, 11, 7, 5], 
     [13, 12, 9, 11, 18, 14, 12], 
     [ 9, 8, 5, 7, 14, 10, 8], 
     [ 7, 6, 3, 5, 12, 8, 6]], dtype=int64) 

और जानकारी:

pd.DataFrame(data=df1.values+df1.values.T,index=df.index,columns=df.index) 
Out[627]: 
ID a b c d e f g 
ID       
a 8 7 4 6 13 9 7 
b 7 6 3 5 12 8 6 
c 4 3 0 2 9 5 3 
d 6 5 2 4 11 7 5 
e 13 12 9 11 18 14 12 
f 9 8 5 7 14 10 8 
g 7 6 3 5 12 8 6 
+0

जब मैं इसे आज़माता हूं तो मुझे एक त्रुटि मिल रही है। मुझे नहीं पता क्यों, लेकिन जब मैं "डीएफ ['आकार'] कोशिश करता हूं। मूल्य + डीएफ ['आकार']। मूल्य।" मुझे मिलता है "सरणी ([10, 0, 12, 8, 16, 0, 16], dtype = int64) "। – atonnerre

+0

@atonnerre इसे फिर से प्रयास करें, मैं 'df1 = df.set_index (' ID ') जोड़ रहा हूं, भ्रम के लिए खेद है। – Wen

+1

कृपया ध्यान दें कि जब मैंने लिखा था तो मैं इंडेक्स को सेट करने का उल्लेख कर रहा था, मैं इसे अपने बारे में सोच सकता था, न कि आपका समाधान जो कि बहुत मूल्यवान है! :) और धन्यवाद, आप भी! – atonnerre

संबंधित मुद्दे