दिलचस्प पोस्ट
एचईएल फाइल से टैग निकालें MySQL क्वेरी से nth रिकॉर्ड लौटें शेल में एक स्ट्रिंग को विभाजित कैसे करें और आखिरी फ़ील्ड प्राप्त करें डॉककर एक सामान्य वर्चुअल मशीन से कैसे अलग है? NSError और __autoreleasing कस्टम संदेश बॉक्स पायथन पीआईपी अधिष्ठापन "कमांड" अजगर setup.py egg_info "त्रुटि कोड 1 के साथ विफल" देता है हैंडल बटन रीसाइक्लिंगदृश्य में एक पंक्ति के अंदर क्लिक करें एक अलग समयक्षेत्र पर वर्ष-महीने-दर-दिन से कैसे एकत्र किया जाए PHP का उपयोग कर MySQL डाटाबेस में आईपी एड्रेस भंडारण इन-लाइन सीएसएस के बारे में क्या बुरा है? कैसे अजगर शब्दकोश में यादृच्छिक मूल्य प्राप्त करने के लिए एकाधिक अनुप्रयोगों के साथ एक asp.net सदस्यता डेटाबेस का उपयोग एकल साइन ऑन AngularJS: एक नई ब्राउज़र विंडो खोलें, फिर भी अभी तक गुंजाइश और नियंत्रक और सेवाओं को बनाए रखा है एंड्रॉइड में दृश्यपेज नियंत्रक की गति धीमी

विभक्त पंक्तियों में विभाजित (विस्फोट) पांडा डेटाफ़्रेम स्ट्रिंग एंट्री

मेरे पास एक pandas dataframe है जिसमें पाठ स्ट्रिंग के एक कॉलम में अल्पविराम से अलग किए गए मान शामिल हैं I मैं प्रत्येक सीएसवी फ़ील्ड को विभाजित करना चाहता हूं और प्रति प्रविष्टि एक नई पंक्ति बनाना चाहता हूं (मान लें कि सीएसवी साफ है और केवल ',' पर विभाजन की जरूरत है)। उदाहरण के लिए, a b चाहिए:

 In [7]: a Out[7]: var1 var2 0 a,b,c 1 1 d,e,f 2 In [8]: b Out[8]: var1 var2 0 a 1 1 b 1 2 c 1 3 d 2 4 e 2 5 f 2 

अब तक, मैंने कई सरल कार्यों की कोशिश की है, लेकिन .apply विधि केवल एक पंक्ति को वापस मान के रूप में स्वीकार करते हैं जब यह अक्ष पर प्रयोग किया जाता है, और मैं नहीं मिल सकता। काम करने के लिए .transform किसी भी सुझाव को सराहा जाएगा!

उदाहरण डेटा:

 from pandas import DataFrame import numpy as np a = DataFrame([{'var1': 'a,b,c', 'var2': 1}, {'var1': 'd,e,f', 'var2': 2}]) b = DataFrame([{'var1': 'a', 'var2': 1}, {'var1': 'b', 'var2': 1}, {'var1': 'c', 'var2': 1}, {'var1': 'd', 'var2': 2}, {'var1': 'e', 'var2': 2}, {'var1': 'f', 'var2': 2}]) 

मैं जानता हूँ कि यह काम नहीं करेगा क्योंकि हम डेटाफीम मेटा-डाटा को नॉर्मी के माध्यम से जाकर खो देते हैं, लेकिन आपको यह समझना चाहिए कि मैंने क्या करने की कोशिश की है:

 def fun(row): letters = row['var1'] letters = letters.split(',') out = np.array([row] * len(letters)) out['var1'] = letters a['idx'] = range(a.shape[0]) z = a.groupby('idx') z.transform(fun) 

Solutions Collecting From Web of "विभक्त पंक्तियों में विभाजित (विस्फोट) पांडा डेटाफ़्रेम स्ट्रिंग एंट्री"

इस जैसे किसी और के बारे में क्या राय है:

 In [55]: pd.concat([Series(row['var2'], row['var1'].split(',')) for _, row in a.iterrows()]).reset_index() Out[55]: index 0 0 a 1 1 b 1 2 c 1 3 d 2 4 e 2 5 f 2 

फिर आपको कॉलम का नाम बदलना होगा

स्वीकार किए जाते हैं उत्तर की तुलना में कुछ तेज खोजने के लिए दर्दनाक प्रयोग के बाद, मुझे यह काम करने के लिए मिला। यह डेटासेट पर लगभग 100 गुना तेजी से चला गया, मैंने इसे कोशिश की।

अगर किसी को यह और अधिक सुरुचिपूर्ण बनाने का एक तरीका है, तो हर तरह से कृपया अपना कोड संशोधित करें। मुझे ऐसा कोई रास्ता नहीं मिल रहा है, जो अन्य कॉलमों को सेट किए बिना काम करता है, जिन्हें आप इंडेक्स के रूप में रखना चाहते हैं और फिर सूचकांक को रीसेट करते हैं और कॉलमों को पुनः नामकरण करते हैं, लेकिन मैं सोचता हूं कि काम करने वाला कुछ और है।

 b = DataFrame(a.var1.str.split(',').tolist(), index=a.var2).stack() b = b.reset_index()[[0, 'var2']] # var1 variable is currently labeled 0 b.columns = ['var1', 'var2'] # renaming var1 

UPDATE2: अधिक सामान्य वेक्टरयुक्त फ़ंक्शन, जो कई normal और एकाधिक list कॉलम के लिए काम करेगा

 def explode(df, lst_cols, fill_value=''): # make sure `lst_cols` is a list if lst_cols and not isinstance(lst_cols, list): lst_cols = [lst_cols] # all columns except `lst_cols` idx_cols = df.columns.difference(lst_cols) # calculate lengths of lists lens = df[lst_cols[0]].str.len() if (lens > 0).all(): # ALL lists in cells aren't empty return pd.DataFrame({ col:np.repeat(df[col].values, df[lst_cols[0]].str.len()) for col in idx_cols }).assign(**{col:np.concatenate(df[col].values) for col in lst_cols}) \ .loc[:, df.columns] else: # at least one list in cells is empty return pd.DataFrame({ col:np.repeat(df[col].values, df[lst_cols[0]].str.len()) for col in idx_cols }).assign(**{col:np.concatenate(df[col].values) for col in lst_cols}) \ .append(df.loc[lens==0, idx_cols]).fillna(fill_value) \ .loc[:, df.columns] 

डेमो:

एकाधिक list कॉलम – सभी list स्तंभों में प्रत्येक पंक्ति में समान # तत्व होने चाहिए:

 In [36]: df Out[36]: aaa myid num text 0 10 1 [1, 2, 3] [aa, bb, cc] 1 11 2 [1, 2] [cc, dd] 2 12 3 [] [] 3 13 4 [] [] In [37]: explode(df, ['num','text'], fill_value='') Out[37]: aaa myid num text 0 10 1 1 aa 1 10 1 2 bb 2 10 1 3 cc 3 11 2 1 cc 4 11 2 2 dd 2 12 3 3 13 4 

सेट अप:

 df = pd.DataFrame({ 'aaa': {0: 10, 1: 11, 2: 12, 3: 13}, 'myid': {0: 1, 1: 2, 2: 3, 3: 4}, 'num': {0: [1, 2, 3], 1: [1, 2], 2: [], 3: []}, 'text': {0: ['aa', 'bb', 'cc'], 1: ['cc', 'dd'], 2: [], 3: []} }) 

सीएसवी कॉलम:

 In [46]: df Out[46]: var1 var2 var3 0 a,b,c 1 XX 1 d,e,f,x,y 2 ZZ In [47]: explode(df.assign(var1=df.var1.str.split(',')), 'var1') Out[47]: var1 var2 var3 0 a 1 XX 1 b 1 XX 2 c 1 XX 3 d 2 ZZ 4 e 2 ZZ 5 f 2 ZZ 6 x 2 ZZ 7 y 2 ZZ 

इस छोटी सी चाल का उपयोग करके हम सीएसवी-जैसी कॉलम को list कॉलम में परिवर्तित कर सकते हैं:

 In [48]: df.assign(var1=df.var1.str.split(',')) Out[48]: var1 var2 var3 0 [a, b, c] 1 XX 1 [d, e, f, x, y] 2 ZZ 

अद्यतनः सामान्य वेक्टरयुक्त दृष्टिकोण (एकाधिक कॉलम के लिए भी काम करेगा):

मूल डीएफ:

 In [177]: df Out[177]: var1 var2 var3 0 a,b,c 1 XX 1 d,e,f,x,y 2 ZZ 

उपाय:

पहले सीएसवी स्ट्रिंग को सूचियों में कनवर्ट करते हैं:

 In [178]: lst_col = 'var1' In [179]: x = df.assign(**{lst_col:df[lst_col].str.split(',')}) In [180]: x Out[180]: var1 var2 var3 0 [a, b, c] 1 XX 1 [d, e, f, x, y] 2 ZZ 

अब हम यह कर सकते हैं:

 In [181]: pd.DataFrame({ ...: col:np.repeat(x[col].values, x[lst_col].str.len()) ...: for col in x.columns.difference([lst_col]) ...: }).assign(**{lst_col:np.concatenate(x[lst_col].values)})[x.columns.tolist()] ...: Out[181]: var1 var2 var3 0 a 1 XX 1 b 1 XX 2 c 1 XX 3 d 2 ZZ 4 e 2 ZZ 5 f 2 ZZ 6 x 2 ZZ 7 y 2 ZZ 

पुराने उत्तर:

@ एफ़िक्लेल्स्टिन समाधान से प्रेरित होकर, मैं इसे थोड़ा और अधिक सामान्यीकृत बनाना चाहता था जो दो से अधिक स्तंभों के साथ डीएफ पर लागू किया जा सकता था और उपवास के रूप में तेजी से, जितनी जल्दी एएफकैल्स्टीन के समाधान के रूप में):

 In [2]: df = pd.DataFrame( ...: [{'var1': 'a,b,c', 'var2': 1, 'var3': 'XX'}, ...: {'var1': 'd,e,f,x,y', 'var2': 2, 'var3': 'ZZ'}] ...: ) In [3]: df Out[3]: var1 var2 var3 0 a,b,c 1 XX 1 d,e,f,x,y 2 ZZ In [4]: (df.set_index(df.columns.drop('var1',1).tolist()) ...: .var1.str.split(',', expand=True) ...: .stack() ...: .reset_index() ...: .rename(columns={0:'var1'}) ...: .loc[:, df.columns] ...: ) Out[4]: var1 var2 var3 0 a 1 XX 1 b 1 XX 2 c 1 XX 3 d 2 ZZ 4 e 2 ZZ 5 f 2 ZZ 6 x 2 ZZ 7 y 2 ZZ 

यह एक सामान्य कार्य के लिए मैंने लिखा एक फ़ंक्शन है Series / stack विधियों की तुलना में यह अधिक कुशल है कॉलम ऑर्डर और नाम रखा जाता है

 def tidy_split(df, column, sep='|', keep=False): """ Split the values of a column and expand so the new DataFrame has one split value per row. Filters rows where the column is missing. Params ------ df : pandas.DataFrame dataframe with the column to split and expand column : str the column to split and expand sep : str the string used to split the column's values keep : bool whether to retain the presplit value as it's own row Returns ------- pandas.DataFrame Returns a dataframe with the same columns as `df`. """ indexes = list() new_values = list() df = df.dropna(subset=[column]) for i, presplit in enumerate(df[column].astype(str)): values = presplit.split(sep) if keep and len(values) > 1: indexes.append(i) new_values.append(presplit) for value in values: indexes.append(i) new_values.append(value) new_df = df.iloc[indexes, :].copy() new_df[column] = new_values return new_df 

इस समारोह के साथ, मूल प्रश्न उतना आसान है जैसे:

 tidy_split(a, 'var1', sep=',') 

इसी तरह के प्रश्न: पांडा: मैं कई स्तंभों में एक कॉलम में पाठ कैसे विभाजित करूं?

तुम यह कर सकते थे:

 >> a=pd.DataFrame({"var1":"a,b,cd,e,f".split(),"var2":[1,2]}) >> s = a.var1.str.split(",").apply(pd.Series, 1).stack() >> s.index = s.index.droplevel(-1) >> del a['var1'] >> a.join(s) var2 var1 0 1 a 0 1 b 0 1 c 1 2 d 1 2 e 1 2 f 

मैं डेटाफ्रेम के लिए कॉलम के मनमानी संख्याओं के साथ एक समाधान के साथ आया (जबकि अभी भी केवल एक कॉलम की प्रविष्टियों को एक समय में अलग करना)।

 def splitDataFrameList(df,target_column,separator): ''' df = dataframe to split, target_column = the column containing the values to split separator = the symbol used to perform the split returns: a dataframe with each entry for the target column separated, with each element moved into a new row. The values in the other columns are duplicated across the newly divided rows. ''' def splitListToRows(row,row_accumulator,target_column,separator): split_row = row[target_column].split(separator) for s in split_row: new_row = row.to_dict() new_row[target_column] = s row_accumulator.append(new_row) new_rows = [] df.apply(splitListToRows,axis=1,args = (new_rows,target_column,separator)) new_df = pandas.DataFrame(new_rows) return new_df 

जेलन के ऊपर से बहुत ही अच्छे उत्तर का इस्तेमाल किया गया था, लेकिन कई स्तंभों को विभाजित करने के लिए विस्तार करने की आवश्यकता थी। सोचा था कि मैं साझा करेगा

 def splitDataFrameList(df,target_column,separator): ''' df = dataframe to split, target_column = the column containing the values to split separator = the symbol used to perform the split returns: a dataframe with each entry for the target column separated, with each element moved into a new row. The values in the other columns are duplicated across the newly divided rows. ''' def splitListToRows(row, row_accumulator, target_columns, separator): split_rows = [] for target_column in target_columns: split_rows.append(row[target_column].split(separator)) # Seperate for multiple columns for i in range(len(split_rows[0])): new_row = row.to_dict() for j in range(len(split_rows)): new_row[target_columns[j]] = split_rows[j][i] row_accumulator.append(new_row) new_rows = [] df.apply(splitListToRows,axis=1,args = (new_rows,target_column,separator)) new_df = pd.DataFrame(new_rows) return new_df 

मैं इस समस्या के निम्नलिखित समाधान के साथ आया हूं:

 def iter_var1(d): for _, row in d.iterrows(): for v in row["var1"].split(","): yield (v, row["var2"]) new_a = DataFrame.from_records([i for i in iter_var1(a)], columns=["var1", "var2"]) 

एक अन्य समाधान जो अजगर कॉपी पैकेज का उपयोग करता है

 import copy new_observations = list() def pandas_explode(df, column_to_explode): new_observations = list() for row in df.to_dict(orient='records'): explode_values = row[column_to_explode] del row[column_to_explode] if type(explode_values) is list or type(explode_values) is tuple: for explode_value in explode_values: new_observation = copy.deepcopy(row) new_observation[column_to_explode] = explode_value new_observations.append(new_observation) else: new_observation = copy.deepcopy(row) new_observation[column_to_explode] = explode_values new_observations.append(new_observation) return_df = pd.DataFrame(new_observations) return return_df df = pandas_explode(df, column_name) 

यहां एक काफी स्पष्ट संदेश है जो पंडस एसआर एक्सेसर से split विधि का उपयोग करता है और फिर प्रत्येक पंक्ति को एक सरणी में समतल करने के लिए NumPy का उपयोग करता है।

संगत मान गैर-विभाजित कॉलम को np.repeat साथ सही संख्या की संख्या को np.repeat

 var1 = df.var1.str.split(',', expand=True).values.ravel() var2 = np.repeat(df.var2.values, len(var1) / len(df)) pd.DataFrame({'var1': var1, 'var2': var2}) var1 var2 0 a 1 1 b 1 2 c 1 3 d 2 4 e 2 5 f 2