2016-05-06 8 views
6

तो। हमारे पास गन्दा डेटा है जो एक टीएसवी फ़ाइल में संग्रहीत डेटा है जिसे मुझे विश्लेषण करने की आवश्यकता है। यह वह जगह है कि यह कैसेपायथन। पांडा। बड़ा डाटा। गन्दा टीएसवी फ़ाइल। डेटा को कैसे घुमाएं?

status=200 protocol=http region_name=Podolsk datetime=2016-03-10 15:51:58 user_ip=0.120.81.243 user_agent=Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36 user_id=7885299833141807155 user_vhost=tindex.ru method=GET page=/search/ 

लग रहा है और समस्या यह है कि पंक्तियों में से कुछ अलग कॉलम आदेश है/उनमें से कुछ मान गुम और मुझे लगता है कि उच्च प्रदर्शन के साथ से छुटकारा पाने की जरूरत है (डेटासेट के बाद से मैं काम कर रहा हूँ 100 गीगाबाइट तक हैं)।

Data = pd.read_table('data/data.tsv', sep='\t+',header=None,names=['status', 'protocol',\ 
                'region_name', 'datetime',\ 
                'user_ip', 'user_agent',\ 
                'user_id', 'user_vhost',\ 
                'method', 'page'], engine='python') 
Clean_Data = (Data.dropna()).reset_index(drop=True) 

अब मैं याद आ रही मूल्यों से छुटकारा मिला लेकिन एक समस्या अभी भी बनी हुई है! यह कैसे डेटा लग रहा है: enter image description here

और यह कैसे समस्या दिखाई देता है: enter image description here

आप देख सकते हैं कॉलम की कुछ भरपाई कर रहे हैं। मैं एक बहुत कम प्रदर्शन समाधान

ids = Clean_Data.index.tolist() 
for column in Clean_Data.columns: 
    for row, i in zip(Clean_Data[column], ids): 
     if np.logical_not(str(column) in row): 
      Clean_Data.drop([i], inplace=True) 
      ids.remove(i) 

तो अब डेटा अच्छा लग रहा है ... कम से कम मैं इसके साथ काम कर सकते हैं बनाया! लेकिन ऊपर दी गई विधि के लिए उच्च प्रदर्शन वैकल्पिक क्या है? unutbu कोड पर

अद्यतन: ट्रेसबैक त्रुटि

--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-4-52c9d76f9744> in <module>() 
     8  df.index.names = ['index', 'num'] 
     9 
---> 10  df = df.set_index('field', append=True) 
    11  df.index = df.index.droplevel(level='num') 
    12  df = df['value'].unstack(level=1) 

/Users/Peter/anaconda/lib/python2.7/site-packages/pandas/core/frame.pyc in set_index(self, keys, drop, append, inplace, verify_integrity) 
    2805    if isinstance(self.index, MultiIndex): 
    2806     for i in range(self.index.nlevels): 
-> 2807      arrays.append(self.index.get_level_values(i)) 
    2808    else: 
    2809     arrays.append(self.index) 

/Users/Peter/anaconda/lib/python2.7/site-packages/pandas/indexes/multi.pyc in get_level_values(self, level) 
    664   values = _simple_new(filled, self.names[num], 
    665        freq=getattr(unique, 'freq', None), 
--> 666        tz=getattr(unique, 'tz', None)) 
    667   return values 
    668 

/Users/Peter/anaconda/lib/python2.7/site-packages/pandas/indexes/range.pyc in _simple_new(cls, start, stop, step, name, dtype, **kwargs) 
    124     return RangeIndex(start, stop, step, name=name, **kwargs) 
    125    except TypeError: 
--> 126     return Index(start, stop, step, name=name, **kwargs) 
    127 
    128   result._start = start 

/Users/Peter/anaconda/lib/python2.7/site-packages/pandas/indexes/base.pyc in __new__(cls, data, dtype, copy, name, fastpath, tupleize_cols, **kwargs) 
    212    if issubclass(data.dtype.type, np.integer): 
    213     from .numeric import Int64Index 
--> 214     return Int64Index(data, copy=copy, dtype=dtype, name=name) 
    215    elif issubclass(data.dtype.type, np.floating): 
    216     from .numeric import Float64Index 

/Users/Peter/anaconda/lib/python2.7/site-packages/pandas/indexes/numeric.pyc in __new__(cls, data, dtype, copy, name, fastpath, **kwargs) 
    105    # with a platform int 
    106    if (dtype is None or 
--> 107      not issubclass(np.dtype(dtype).type, np.integer)): 
    108     dtype = np.int64 
    109 

TypeError: data type "index" not understood 

पांडा संस्करण: 0.18.0-np110py27_0

अद्यतन

सब कुछ काम किया ... धन्यवाद हर कोई!

उत्तर

5

मान लीजिए आप इस जैसे TSV डेटा था:

status=A protocol=B region_name=C datetime=D user_ip=E user_agent=F user_id=G 
user_id=G status=A region_name=C user_ip=E datetime=D user_agent=F protocol=B 
protocol=B  datetime=D status=A user_ip=E user_agent=F user_id=G 

क्षेत्रों के आदेश scambled जा सकता है और हो सकता है लापता मूल्य। हालांकि, आपको पंक्तियों को छोड़ना नहीं है क्योंकि फ़ील्ड एक निश्चित क्रम में प्रकट नहीं होते हैं। आप सही कॉलम में मान रखने के लिए पंक्ति डेटा में दिए गए फ़ील्ड नामों का उपयोग कर सकते हैं।उदाहरण के लिए,

import pandas as pd 

df = pd.read_table('data/data.tsv', sep='\t+',header=None, engine='python') 
df = df.stack().str.extract(r'([^=]*)=(.*)', expand=True).dropna(axis=0) 
df.columns = ['field', 'value'] 

df = df.set_index('field', append=True) 
df.index = df.index.droplevel(level=1) 
df = df['value'].unstack(level=1) 

print(df) 

पैदावार

field datetime protocol region_name status user_agent user_id user_ip 
index                 
0   D  B   C  A   F  G  E 
1   D  B   C  A   F  G  E 
2   D  B  None  A   F  G  E 

एक बड़ी TSV फ़ाइल को संभालने के लिए, आपको मात्रा में पंक्तियों संसाधित कर सकते हैं, और फिर अंत में एक DataFrame में संसाधित हिस्सा श्रेणीबद्ध:

import pandas as pd 

chunksize =  # the number of rows to be processed per iteration 
dfs = [] 
reader = pd.read_table('data/data.tsv', sep='\t+',header=None, engine='python', 
         iterator=True, chunksize=chunksize) 
for df in reader: 
    df = df.stack().str.extract(r'([^=]*)=(.*)', expand=True).dropna(axis=0) 
    df.columns = ['field', 'value'] 
    df.index.names = ['index', 'num'] 

    df = df.set_index('field', append=True) 
    df.index = df.index.droplevel(level='num') 
    df = df['value'].unstack(level=1) 
    dfs.append(df) 

df = pd.concat(dfs, ignore_index=True) 
print(df) 

स्पष्टीकरण: दिया गया df:

In [527]: df = pd.DataFrame({0: ['status=A', 'user_id=G', 'protocol=B'], 
1: ['protocol=B', 'status=A', 'datetime=D'], 
2: ['region_name=C', 'region_name=C', 'status=A'], 
3: ['datetime=D', 'user_ip=E', 'user_ip=E'], 
4: ['user_ip=E', 'datetime=D', 'user_agent=F'], 
5: ['user_agent=F', 'user_agent=F', 'user_id=G'], 
6: ['user_id=G', 'protocol=B', None]}); df 
    .....: .....: .....: .....: .....: .....: .....: 
Out[527]: 
      0   1    2   3    4    5   6 
0 status=A protocol=B region_name=C datetime=D  user_ip=E user_agent=F user_id=G 
1 user_id=G status=A region_name=C user_ip=E datetime=D user_agent=F protocol=B 
2 protocol=B datetime=D  status=A user_ip=E user_agent=F  user_id=G  None 

आप किसी एकल स्तंभ में सभी मूल्यों को सम्मिलित कर सकते हैं

In [449]: df.stack() 
Out[449]: 
0 0   status=A 
    1  protocol=B 
    2 region_name=C 
    3  datetime=D 
    4  user_ip=E 
    5  user_agent=F 
    6  user_id=G 
1 0  user_id=G 
    1   status=A 
    2 region_name=C 
    3  user_ip=E 
    4  datetime=D 
    5  user_agent=F 
    6  protocol=B 
2 0  protocol=B 
    1  datetime=D 
    2   status=A 
    3  user_ip=E 
    4  user_agent=F 
    5  user_id=G 
dtype: object 

और फिर लागू .str.extract(r'([^=]*)=(.*)') मूल्य से फ़ील्ड नाम को अलग करने के:

In [450]: df = df.stack().str.extract(r'([^=]*)=(.*)', expand=True).dropna(axis=0); df 
Out[450]: 
       0 1 
0 0  status A 
    1  protocol B 
    2 region_name C 
    3  datetime D 
    4  user_ip E 
    5 user_agent F 
    6  user_id G 
1 0  user_id G 
    1  status A 
    2 region_name C 
    3  user_ip E 
    4  datetime D 
    5 user_agent F 
    6  protocol B 
2 0  protocol B 
    1  datetime D 
    2  status A 
    3  user_ip E 
    4 user_agent F 
    5  user_id G 

यह आसान बनाने के लिए डेटाफ्रेम के कुछ हिस्सों को संदर्भित करने के लिए, कॉलम और इंडेक्स स्तर वर्णनात्मक नाम दें:

In [530]: df.columns = ['field', 'value']; df.index.names = ['index', 'num']; df 
Out[530]: 
       field value 
index num     
0  0   status  A 
     1  protocol  B 
... 

अब अगर हम सूचकांक में field स्तंभ के लिए कदम:

In [531]: df = df.set_index('field', append=True); df 
Out[531]: 
         value 
index num field    
0  0 status   A 
     1 protocol  B 
     2 region_name  C 
     3 datetime  D 
... 

और num सूचकांक स्तर ड्रॉप:

In [532]: df.index = df.index.droplevel(level='num'); df 
Out[532]: 
        value 
index field    
0  status   A 
     protocol  B 
     region_name  C 
     datetime  D 
... 

तो हम द्वारा वांछित प्रपत्र के DataFrame प्राप्त कर सकते हैं field इंडेक्स स्तर को कॉलम इंडेक्स में ले जाना:

In [533]: df = df['value'].unstack(level=1); df 
Out[533]: 
field datetime protocol region_name status user_agent user_id user_ip 
index                 
0   D  B   C  A   F  G  E 
1   D  B   C  A   F  G  E 
2   D  B  None  A   F  G  E 
+0

क्या आप कृपया अपना कोड टिप्पणी कर सकते हैं ताकि मैं (और हर कोई) पूरी तरह से आपका अनुसरण कर सके? एचएम ऐसा लगता है कि iPython उस कोड के साथ वास्तव में धीमा काम करता है। असल में यह 'डीएफ = डीएफ [' सब '] पर अटक गया। Str.extract (' \ t'.join (['(। *)'] * (एन + 1)), विस्तार = सही) 'पंक्ति .. । कोई विचार? –

+0

मैंने कोड बदल दिया है (इसलिए यह अब उस लाइन का उपयोग नहीं करता है) और खंडों में एक टीएसवी फ़ाइल को पढ़ने के तरीके पर एक अनुभाग जोड़ा गया। यदि चंक्साइज बहुत बड़ा नहीं है तो आपको परिणाम अधिक तेज़ी से देखने में सक्षम होना चाहिए। इसके अलावा, शायद आपको एक विशाल डेटाफ्रेम बनाने की आवश्यकता नहीं है; शायद आप टीएसवी को क्रमशः हिस्सों में संसाधित कर सकते हैं। – unutbu

+0

'df = df.set_index ('field', append = True) 'फेंकता है' टाइपरर: डेटा प्रकार" अनुक्रमणिका "समझा नहीं गया है ... आप मेरी [डेटा फ़ाइल (केवल 30 एमबी)] (https: // drive.google.com/open?id=0BxWmwAIo1D_nUUpqTU5TdDlaUHc) ... वास्तव में मुझे कोई संकेत नहीं है क्यों। लगता है कि एक पांडा बग –

4

आप पांडा 'vectorized string operations, विशेष रूप से str.contains उपयोग कर सकते हैं:

import numpy as np 

# boolean index of rows to keep 
is_valid = np.ones(Clean_data.shape[0], np.bool) 

for column in Clean_Data.columns: 

    # check whether rows contain this column name 
    is_valid &= Clean_Data[column].str.contains(column) 

# drop rows where not all elements contain their respective column names 
Clean_Data.drop(np.where(~is_valid)[0], inplace=True) 
+0

'---------------------------------------------- ----------------------------- वैल्यूएरर ट्रेसबैक (सबसे हालिया कॉल अंतिम) में() 8 # जांचें कि पंक्तियों में इस कॉलम का नाम ----> 9 is_valid & = Clean_Data [कॉलम] .str है।इसमें (कॉलम) 11 # ड्रॉप पंक्तियां जहां सभी तत्वों में उनके संबंधित कॉलम नाम नहीं होते हैं ValueError: ऑपरेटरों को आकार (10,) (75618,) (10,) ' –

+0

के साथ एक साथ प्रसारित नहीं किया जा सका, क्षमा करें, वहां था 'is_valid' की शुरुआत में एक टाइपो। अब कोशिश करो। –

3

मैं टिप्पणियां नहीं जोड़ सकता, इसलिए मैं इसे एक उत्तर के रूप में पोस्ट करूंगा (वास्तव में यह स्मृति उपयोग और रनटाइम के बारे में आपकी टिप्पणी के जवाब में एक टिप्पणी है)।

बड़ी चीजें (100 जीबी) के लिए आपको एक बात पर विचार करने की आवश्यकता है, यह है कि आप इन फ़ाइलों को स्मृति में नहीं पढ़ रहे हैं। आप पांडा “Large data” work flows using pandas या How to read a 6 GB csv file with pandas के लिए खंड आकार सेट कर सकते हैं, या सीएसवी मॉड्यूल के साथ उपज जनरेटर का उपयोग कर सकते हैं और लाइन पंक्ति/पंक्ति फ़ाइलों को पढ़ सकते हैं। होना चाहिए - Reading a huge .csv in python

@ unutbu की टिप्पणी को शामिल कॉलम में प्रविष्टियों को क्रमबद्ध करने के लिए regex का उपयोग कर के बारे में, यह देखते हुए कि fieldnames इतनी स्पष्ट रूप से प्रत्येक कोशिका के लिए सीमांकन किया है (यद्यपि वहाँ कुछ त्रुटि जरूरत सुधार हो सकता है यानी r'(.*)=(.*)' कि सभी आवश्यक है) आपको जो भी चाहिए वह भी (जैसा कि वे कहते हैं, कुछ गायब डेटा की वजह से पूरी पंक्तियां छोड़ना एक ठेठ, या अनुशंसित, दृष्टिकोण नहीं है)।

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