संदर्भ

मुझे दूसरी पंक्ति से शुरू करने के लिए पंडों का उपयोग करके एक एल्गोरिदम कोड करने की आवश्यकता है, पिछली पंक्ति से कॉलम मान घटाएं, और परिणाम का उपयोग अगली पंक्ति को घटाने के लिए करें।

उदाहरण

INPUT:
ID    VALUE
0       1
1       10
2       30
3       45
4       78

OUTPUT (just the result, not the operation itself):
ID    VALUE
0       1
1       9  #(10-1)
2       21 #(30-9)
3       24 #(45-21)
4       54 #(78-24)

मैंने क्या कोशिश की

df['VALUE'] = df['VALUE'] - df['VALUE]'.shift() # Doesn't starts with the second row, and use the original dataframe to subtract

df['VALUE'] = df['VALUE'].diff() # Doesn't starts with the second row, and use the original dataframe to subtract
4
Lodi 12 सितंबर 2018, 16:35

3 जवाब

सबसे बढ़िया उत्तर

Numpy, cumsum बारी-बारी से संकेत के साथ

i = np.arange(len(df))
j = np.arange(2)

a = np.where(
    (i[:, None] + j) % 2 == 0, 1, -1
) * df.VALUE.values[:, None]

b = a.cumsum(0)[i, i % 2]

df.assign(VALUE=b)

   ID  VALUE
0   0      1
1   1      9
2   2     21
3   3     24
4   4     54

व्याख्या

पहली बात यह ध्यान रखना है कि

X0 ->                     X0
X1 ->                X1 - X0
X2 ->           X2 - X1 + X0
X3 ->      X3 - X2 + X1 - X0
X4 -> X4 - X3 + X2 - X1 + X0

इसलिए मैं हर दूसरी पंक्ति को ऋणात्मक से गुणा करना चाहता था ... लेकिन वैकल्पिक पंक्तियों के दूसरे विकल्प के लिए मुझे इसे दो बार करने की आवश्यकता थी।

मुझे एक ऐसा मुखौटा बनाने की ज़रूरत थी जो दोनों विकल्पों के लिए + और - 1 के बीच स्वैप हो

i = np.arange(len(df))
j = np.arange(2)

m = np.where(
    (i[:, None] + j) % 2 == 0, 1, -1
)

m

array([[ 1, -1],
       [-1,  1],
       [ 1, -1],
       [-1,  1],
       [ 1, -1]])

अब मुझे इसे अपने df.VALUE में गुणा करके प्रसारित करने की आवश्यकता है

a = m * df.VALUE.values[:, None]

a

array([[  1,  -1],
       [-10,  10],
       [ 30, -30],
       [-45,  45],
       [ 78, -78]])

पैटर्न पर ध्यान दें। अब मैं cumsum

a.cumsum(0)

array([[  1,  -1],
       [ -9,   9],
       [ 21, -21],
       [-24,  24],
       [ 54, -54]])

लेकिन मुझे सकारात्मक लोगों की जरूरत है... अधिक विशेष रूप से, मुझे वैकल्पिक वाले की जरूरत है। तो मैं एक संशोधित arange के साथ टुकड़ा करता हूँ

b = a.cumsum(0)[i, i % 2]
b

array([ 1,  9, 21, 24, 54])

यही वह है जिसे मैंने मौजूदा कॉलम को असाइन करना समाप्त कर दिया है

df.assign(VALUE=b)

   ID  VALUE
0   0      1
1   1      9
2   2     21
3   3     24
4   4     54

यह df की एक प्रति बनाता है और VALUE कॉलम को b से अधिलेखित कर देता है।
इस उत्तर को जारी रखने के लिए, यदि आप चाहें तो किसी नए नाम या df को पुन: असाइन करना सुनिश्चित करें।

df_new = df.assign(VALUE=b)
9
piRSquared 12 सितंबर 2018, 17:15

यह कहना मुश्किल है कि ऐसा करने का कोई पांडा तरीका है या नहीं, मैंने यह सवाल कुछ महीने पहले पूछा था। और नीचे मेरा समाधान है।

l=[]
for x,y in enumerate(df.VALUE):
    if x ==0: 
       l.append(y)
    else : 
       l.append(y-l[x-1])
l
Out[20]: [1, 9, 21, 24, 54]
3
BENY 12 सितंबर 2018, 16:46

यह काम करना चाहिए:

df = pd.DataFrame({"ID": [0, 1, 2, 3, 4], 
                   "VALUE": [1, 10, 30, 45, 78]})
cumsum_with_parity = df.groupby(df.index % 2).VALUE.cumsum()
df["VALUE"] = cumsum_with_parity - cumsum_with_parity.shift().fillna(0)
1
Colin 12 सितंबर 2018, 16:59