পান্ডাসে ডেটাফ্রেমে পূর্ববর্তী সারির মানটি ব্যবহার করার কোনও উপায় আছে ly অ্যাপ্লিকেশনটিতে যখন আগের মানটি প্রয়োগেও গণনা করা হয়?


94

আমার কাছে নিম্নলিখিত ডেটাফ্রেম রয়েছে:

 Index_Date    A    B    C    D
 ===============================
 2015-01-31    10   10   Nan  10
 2015-02-01     2    3   Nan  22 
 2015-02-02    10   60   Nan  280
 2015-02-03    10   100   Nan  250

প্রয়োজনীয়:

 Index_Date    A    B    C    D
 ===============================
 2015-01-31    10   10   10   10
 2015-02-01     2    3   23   22
 2015-02-02    10   60   290  280
 2015-02-03    10   100  3000 250

Column Cজন্য প্রাপ্ত করা হয় 2015-01-31গ্রহণ করে valueএর D

তারপর আমি ব্যবহার করতে হবে valueএর Cজন্য 2015-01-31দ্বারা এবং সংখ্যাবৃদ্ধি valueএর Aউপর 2015-02-01যোগ B

আমি এর চেষ্টা করেছি applyএবং এর দ্বারা একটি shiftব্যবহার করে if elseএকটি মূল ত্রুটি পাওয়া যায়।


কেন ডেটাফ্রেমে আপনার শেষ সারিগুলি কলামগুলির জন্য আলাদা Aএবং B?
আন্তন প্রোটোপোপভ

@ অ্যান্টন এখনই এটির সঠিক ক্ষমা চাইছেন।
ctrl-alt-মোছা

কলাম Aএবং কলামে পরবর্তী সারির মান কত D?
jezrael

7
এটা একটা ভালো প্রশ্ন। আমার ভেক্টরাইজড দ্রবণটির জন্য একই রকম প্রয়োজন। এটি খুব ভাল হবে যদি প্যান্ডাসের সংস্করণ সরবরাহ করা হয় apply()যেখানে ব্যবহারকারীর ফাংশন তার গণনার অংশ হিসাবে পূর্বের সারিতে এক বা একাধিক মান অ্যাক্সেস করতে সক্ষম হয় বা কমপক্ষে একটি পুনঃনির্মাণের পরে পরবর্তী পুনরাবৃত্তিতে 'নিজেই' পাস করা একটি মান ফেরত দেয় return এটি কি লুপের সাথে তুলনা করে কিছু দক্ষতা লাভের অনুমতি দেয় না?
বিল

@ বিল, আপনি এই উত্তরটি সম্পর্কে আগ্রহী হতে পারেন আমি কেবল যুক্ত করেছি, numbaপ্রায়শই এখানে একটি ভাল বিকল্প।
জেপিপি

উত্তর:


64

প্রথমে উদ্ভূত মানটি তৈরি করুন:

df.loc[0, 'C'] = df.loc[0, 'D']

তারপরে অবশিষ্ট সারিতে পুনরাবৃত্তি করুন এবং গণনা করা মানগুলি পূরণ করুন:

for i in range(1, len(df)):
    df.loc[i, 'C'] = df.loc[i-1, 'C'] * df.loc[i, 'A'] + df.loc[i, 'B']


  Index_Date   A   B    C    D
0 2015-01-31  10  10   10   10
1 2015-02-01   2   3   23   22
2 2015-02-02  10  60  290  280

41
লন্ড ছাড়া এটি করার জন্য পান্ডাসে কোনও ফাংশন আছে?
সিটিআরএল-ওএলটি - মুছে দিন

4
গণনার পুনরাবৃত্ত প্রকৃতি যেখানে পূর্ববর্তী পদক্ষেপের ফলাফলের উপর ইনপুটগুলি নির্ভর করে ভেক্টরাইজেশনকে জটিল করে তোলে। আপনি সম্ভবত applyএমন কোনও ফাংশন ব্যবহার করতে পারেন যা লুপের মতো একই গণনা করে তবে পর্দার আড়ালে এটিও একটি লুপ হবে। pandas.pydata.org/pandas-docs/version/0.17.1/generated/…
স্টেফান

যদি আমি এই লুপটি ব্যবহার করি এবং একীভূত ডেটাফ্রেমে গণনা করি এবং এটি একটি ন্যান খুঁজে পায় তবে এটি কেবল ন্যানের সাথে সারি করে। কোনও ত্রুটি নিক্ষেপ করা হয় না, যদি আমি একটি পূরণ করার চেষ্টা করি তবে আমি অ্যাট্রিবিউট এরির পাই: 'numpy.float64' অবজেক্টটির কোনও বৈশিষ্ট্য নেই 'ফিলেনা' ন্যান দিয়ে সারিটি এড়িয়ে যাওয়ার কোনও উপায় আছে কি শূন্যতে মান সেট করা আছে?
ctrl-alt-মোছা

আপনি কি ব্যতীত অন্য কলামগুলিতে মান অনুপস্থিত বলতে চান C?
স্টিফান

হ্যাঁ আপনার সমাধান ঠিক আছে। আমি কেবল লুপের আগে ডেটাফ্রেমে ন্যানগুলি পূরণ করার বিষয়টি নিশ্চিত করি।
সিটিআরএল-ওএলটি - মুছে দিন

41

সংখ্যার একটি কলাম দেওয়া হয়েছে:

lst = []
cols = ['A']
for a in range(100, 105):
    lst.append([a])
df = pd.DataFrame(lst, columns=cols, index=range(5))
df

    A
0   100
1   101
2   102
3   103
4   104

আপনি আগের সারিটি শিফট সহ উল্লেখ করতে পারেন:

df['Change'] = df.A - df.A.shift(1)
df

    A   Change
0   100 NaN
1   101 1.0
2   102 1.0
3   103 1.0
4   104 1.0

9
এটি এই পরিস্থিতিতে সাহায্য করবে না কারণ পূর্ববর্তী সারির মান শুরুতে জানা যায়নি। এটি প্রতিটি পুনরাবৃত্তি গণনা করতে হবে এবং তারপরে পরবর্তী পুনরাবৃত্তিতে ব্যবহার করতে হবে।
বিল

6
আমি এখনও এই উত্তরের জন্য কৃতজ্ঞ কারণ আমি এটির পিছনে হোঁচট খেয়েছি, এমন একটি সন্ধান করছি যেখানে আমি আগের সারির মানটি জানি know তাই ধন্যবাদ @ কেজিটিড
কেভিন

28

numba

পুনরাবৃত্ত গণনার জন্য যা ভেক্টরিরিজ নয় numba, যা জেআইটি-সংকলন ব্যবহার করে এবং নিম্ন স্তরের অবজেক্টগুলির সাথে কাজ করে, প্রায়শই বড় পারফরম্যান্সের উন্নতি লাভ করে। আপনার কেবলমাত্র একটি নিয়মিত forলুপ সংজ্ঞায়িত করতে হবে এবং ডেকরেটার ব্যবহার করতে হবে @njitবা (পুরানো সংস্করণগুলির জন্য) @jit(nopython=True):

যুক্তিসঙ্গত আকারের ডেটাফ্রেমের জন্য, এটি নিয়মিত forলুপের তুলনায় ~ 30x এর কার্যকারিতা উন্নতি করে :

from numba import jit

@jit(nopython=True)
def calculator_nb(a, b, d):
    res = np.empty(d.shape)
    res[0] = d[0]
    for i in range(1, res.shape[0]):
        res[i] = res[i-1] * a[i] + b[i]
    return res

df['C'] = calculator_nb(*df[list('ABD')].values.T)

n = 10**5
df = pd.concat([df]*n, ignore_index=True)

# benchmarking on Python 3.6.0, Pandas 0.19.2, NumPy 1.11.3, Numba 0.30.1
# calculator() is same as calculator_nb() but without @jit decorator
%timeit calculator_nb(*df[list('ABD')].values.T)  # 14.1 ms per loop
%timeit calculator(*df[list('ABD')].values.T)     # 444 ms per loop

4
এটা চমৎকার! আমি আমার ফাংশনটিকে ত্বরান্বিত করেছি, যা পূর্ববর্তী মানগুলি থেকে মান গণনা করে। ধন্যবাদ!
আর্টেম মালেকভ

20

নাম্পার অ্যারেগুলিতে পুনরাবৃত্ত ফাংশন প্রয়োগ করা বর্তমান উত্তরের চেয়ে দ্রুত হবে।

df = pd.DataFrame(np.repeat(np.arange(2, 6),3).reshape(4,3), columns=['A', 'B', 'D'])
new = [df.D.values[0]]
for i in range(1, len(df.index)):
    new.append(new[i-1]*df.A.values[i]+df.B.values[i])
df['C'] = new

আউটপুট

      A  B  D    C
   0  1  1  1    1
   1  2  2  2    4
   2  3  3  3   15
   3  4  4  4   64
   4  5  5  5  325

4
এই উত্তরটি আমার জন্য অনুরূপ গণনার সাথে পুরোপুরি কাজ করে। আমি সিউসাম এবং শিফ্টের সংমিশ্রণটি ব্যবহার করার চেষ্টা করেছি তবে এই সমাধানটি আরও ভালভাবে কাজ করে। ধন্যবাদ
সাইমন

ধন্যবাদ এটি আমার জন্যও নিখুঁত কাজ করে। আমি অনেক ধরণের আইেরো, ইটারটুপলস, প্রয়োগ এবং আরও অনেকগুলি নিয়ে লড়াই করে যাচ্ছিলাম এবং এটি বুঝতে এবং সম্পাদন করা সহজ বলে মনে হচ্ছে।

9

যদিও এই প্রশ্নটি জিজ্ঞাসা করার পরে অনেক সময় হয়ে গেছে, আমি কারওর সাহায্যের আশায় আমার উত্তর পোস্ট করব।

দাবি অস্বীকার: আমি জানি এই সমাধানটি মান নয় , তবে আমি মনে করি এটি ভালভাবে কাজ করে।

import pandas as pd
import numpy as np

data = np.array([[10, 2, 10, 10],
                 [10, 3, 60, 100],
                 [np.nan] * 4,
                 [10, 22, 280, 250]]).T
idx = pd.date_range('20150131', end='20150203')
df = pd.DataFrame(data=data, columns=list('ABCD'), index=idx)
df
               A    B     C    D
 =================================
 2015-01-31    10   10    NaN  10
 2015-02-01    2    3     NaN  22 
 2015-02-02    10   60    NaN  280
 2015-02-03    10   100   NaN  250

def calculate(mul, add):
    global value
    value = value * mul + add
    return value

value = df.loc['2015-01-31', 'D']
df.loc['2015-01-31', 'C'] = value
df.loc['2015-02-01':, 'C'] = df.loc['2015-02-01':].apply(lambda row: calculate(*row[['A', 'B']]), axis=1)
df
               A    B     C     D
 =================================
 2015-01-31    10   10    10    10
 2015-02-01    2    3     23    22 
 2015-02-02    10   60    290   280
 2015-02-03    10   100   3000  250

সুতরাং মূলত আমরা applyপান্ডাস থেকে একটি এবং একটি বিশ্বব্যাপী ভেরিয়েবলের সহায়তা ব্যবহার করি যা পূর্ববর্তী গণনা করা মানটিকে ট্র্যাক করে।


একটি forলুপের সাথে সময়ের তুলনা :

data = np.random.random(size=(1000, 4))
idx = pd.date_range('20150131', end='20171026')
df = pd.DataFrame(data=data, columns=list('ABCD'), index=idx)
df.C = np.nan

df.loc['2015-01-31', 'C'] = df.loc['2015-01-31', 'D']

%%timeit
for i in df.loc['2015-02-01':].index.date:
    df.loc[i, 'C'] = df.loc[(i - pd.DateOffset(days=1)).date(), 'C'] * df.loc[i, 'A'] + df.loc[i, 'B']

৩.২ এস 2 ১১৪ এমএস প্রতি লুপ (অর্থাত্ ± স্ট্যান্ড ডেভেল 7 রান, প্রতি 1 টি লুপ)

data = np.random.random(size=(1000, 4))
idx = pd.date_range('20150131', end='20171026')
df = pd.DataFrame(data=data, columns=list('ABCD'), index=idx)
df.C = np.nan

def calculate(mul, add):
    global value
    value = value * mul + add
    return value

value = df.loc['2015-01-31', 'D']
df.loc['2015-01-31', 'C'] = value

%%timeit
df.loc['2015-02-01':, 'C'] = df.loc['2015-02-01':].apply(lambda row: calculate(*row[['A', 'B']]), axis=1)

প্রতি লুপটিতে 1.82 s ± 64.4 এমএস (7 runs রানের গড় ± স্ট্যান্ড। ডিভ। প্রতিটি লুপ প্রতিটি)

সুতরাং গড়ে 0.57 গুণ দ্রুত।


0

সাধারণভাবে, একটি স্পষ্ট লুপ এড়িয়ে চাবির মূলটি হ'ল রোইনডেক্স -১ == রাউইনডেক্সে ডেটাফ্রেমের 2 টি দৃষ্টান্তে যোগদান (সংহত) হওয়া।

তারপরে আপনার কাছে r এবং r-1 এর সারি যুক্ত একটি বড় ডেটাফ্রেম থাকবে, যেখান থেকে আপনি df.apply () ফাংশন করতে পারবেন।

তবে বড় ডেটাসেট তৈরির ওভারহেড সমান্তরাল প্রক্রিয়াজাতকরণের সুবিধাগুলি অফসেট করতে পারে ...

এইচটিএইচ মার্টিন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.