2012-12-20 6 views
12

में कनवर्ट करना मैंने अभी मैटलैब से पायथन 2.7 तक आगे बढ़ना शुरू किया और मुझे अपनी .mat-files पढ़ने में कुछ परेशानी है। मैटलैब के डेटनम प्रारूप में समय की जानकारी संग्रहीत की जाती है। उन लोगों के लिए जो इससे परिचित नहीं हैं:मैटलैब के डेटनम प्रारूप को पाइथन

एक धारावाहिक दिनांक संख्या एक कैलेंडर तिथि को निर्धारित दिनांक तिथि के बाद पारित दिनों की संख्या के रूप में दर्शाती है। MATLAB में, धारावाहिक दिनांक संख्या 1 जनवरी 1, 0000 है।

MATLAB मध्यरात्रि से शुरू होने वाले दिनों के अंशों का प्रतिनिधित्व करने के लिए धारावाहिक समय का भी उपयोग करता है; उदाहरण के लिए, 6 पीएम 0.75 सीरियल दिनों के बराबर है। इसलिए MATLAB में '31-ऑक्टो-2003, 6:00 अपराह्न 'स्ट्रिंग दिनांक संख्या 731885.75 है।

(मैटलैब प्रलेखन से लिया)

मैं अजगर समय प्रारूप में बदलने के लिए करना चाहते हैं और मैं this tutorial पाया। संक्षेप में, लेखक कहा गया है कि

आप पार्स यदि यह अजगर का उपयोग datetime.fromordinal(731965.04835648148) तो परिणाम लग सकता है उचित [...]

(किसी भी आगे रूपांतरण से पहले), जिसके लिए काम नहीं करता है मुझे, के बाद से datetime.fromordinal एक पूर्णांक उम्मीद:

>>> datetime.fromordinal(731965.04835648148) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: integer argument expected, got float 

जबकि मैं सिर्फ उन्हें दौर दैनिक डेटा के लिए नीचे, मैं वास्तव में प्रतिमिनट समय श्रृंखला आयात करने की आवश्यकता सकता है। क्या किसी को इस समस्या का समाधान है? मैं अपनी .mat फ़ाइलों को दोबारा सुधारने से बचना चाहता हूं क्योंकि उनमें से बहुत से हैं और मेरे सहयोगियों को भी उनके साथ काम करने की ज़रूरत है।

यदि यह मदद करता है, someone else asked for the other way round। अफसोस की बात है, मैं वास्तव में समझने के लिए पाइथन के लिए बहुत नया हूं कि वहां क्या हो रहा है।

/संपादित करें (2012-11-01): यह ऊपर पोस्ट किए गए ट्यूटोरियल में तय किया गया है।

उत्तर

13

आप समाधान से लिंक करते हैं, इसकी एक छोटी समस्या है। यह इस प्रकार है:

python_datetime = datetime.fromordinal(int(matlab_datenum)) + timedelta(days=matlab_datenum%1) - timedelta(days = 366) 

एक लंबे समय तक स्पष्टीकरण here

+1

मैं 'यह' fromordinal' में खिलाने से पहले एक 'int' को matlab_datenum' परिवर्तित होगी। – Blender

+1

@ ब्लेंडर: आप सही हैं। तय की। – carlosdc

+0

या सरल: 'python_datetime = datetime.fromordinal (int (matlab_datenum) - 366) + timedelta (days = matlab_datenum% 1)' :) –

7

पाया जा सकता है बस के मामले में यह दूसरों के लिए उपयोगी है, यहाँ एक मैटलैब चटाई फ़ाइल से लोड हो रहा है समय श्रृंखला डेटा की एक पूरी उदाहरण है, का एक वेक्टर परिवर्तित carlosdc के जवाब (एक समारोह के रूप में परिभाषित किया गया) का उपयोग कर, और फिर datetime वस्तुओं की एक सूची के लिए Matlab datenums पांडा के साथ समय श्रृंखला के रूप में की साजिश रचने:

from scipy.io import loadmat 
import pandas as pd 
import datetime as dt 
import urllib 

# In Matlab, I created this sample 20-day time series: 
# t = datenum(2013,8,15,17,11,31) + [0:0.1:20]; 
# x = sin(t) 
# y = cos(t) 
# plot(t,x) 
# datetick 
# save sine.mat 

urllib.urlretrieve('http://geoport.whoi.edu/data/sine.mat','sine.mat'); 

# If you don't use squeeze_me = True, then Pandas doesn't like 
# the arrays in the dictionary, because they look like an arrays 
# of 1-element arrays. squeeze_me=True fixes that. 

mat_dict = loadmat('sine.mat',squeeze_me=True) 

# make a new dictionary with just dependent variables we want 
# (we handle the time variable separately, below) 
my_dict = { k: mat_dict[k] for k in ['x','y']} 

def matlab2datetime(matlab_datenum): 
    day = dt.datetime.fromordinal(int(matlab_datenum)) 
    dayfrac = dt.timedelta(days=matlab_datenum%1) - dt.timedelta(days = 366) 
    return day + dayfrac 

# convert Matlab variable "t" into list of python datetime objects 
my_dict['date_time'] = [matlab2datetime(tval) for tval in mat_dict['t']] 

# print df 
<class 'pandas.core.frame.DataFrame'> 
DatetimeIndex: 201 entries, 2013-08-15 17:11:30.999997 to 2013-09-04 17:11:30.999997 
Data columns (total 2 columns): 
x 201 non-null values 
y 201 non-null values 
dtypes: float64(2) 

# plot with Pandas 
df = pd.DataFrame(my_dict) 
df = df.set_index('date_time') 
df.plot() 

enter image description here

+0

निश्चित रूप से उपयोगी, आपका कोड साझा करने के लिए धन्यवाद। –

2

बस पिछले टिप्पणियों पर निर्माण और जोड़ना। कुंजी toordinal विधि और datetime और संबंधित उप-वर्गों में कन्स्ट्रक्टर fromordinal द्वारा किए गए दिन की गणना की जा रही है। उदाहरण के लिए, Python Library Reference for 2.7 से, पढ़ता है कि fromordinal

वापसी तिथि proleptic ग्रेगोरियन क्रमसूचक, जहां जनवरी 1 का 1 है क्रमसूचक 1 करने के लिए इसी। ValueError तब तक उठाया जाता है जब तक कि= ordinal < = date.max.toordinal()।

हालांकि, वर्ष 0 एडी अभी भी एक (लीप) वर्ष गिनने के लिए है, इसलिए अभी भी 366 दिन हैं जिन्हें ध्यान में रखना आवश्यक है। (लीप वर्ष में था, 2016 की तरह 504 चार साल के चक्र पहले यह है कि वास्तव में।)

इन दोनों कार्यों कि मैं समान उद्देश्यों के लिए उपयोग किया गया है कर रहे हैं: और

import datetime 

def datetime_pytom(d,t): 
''' 
Input 
    d Date as an instance of type datetime.date 
    t Time as an instance of type datetime.time 
Output 
    The fractional day count since 0-Jan-0000 (proleptic ISO calendar) 
    This is the 'datenum' datatype in matlab 
Notes on day counting 
    matlab: day one is 1 Jan 0000 
    python: day one is 1 Jan 0001 
    hence an increase of 366 days, for year 0 AD was a leap year 
''' 
dd = d.toordinal() + 366 
tt = datetime.timedelta(hours=t.hour,minutes=t.minute, 
         seconds=t.second) 
tt = datetime.timedelta.total_seconds(tt)/86400 
return dd + tt 

def datetime_mtopy(datenum): 
''' 
Input 
    The fractional day count according to datenum datatype in matlab 
Output 
    The date and time as a instance of type datetime in python 
Notes on day counting 
    matlab: day one is 1 Jan 0000 
    python: day one is 1 Jan 0001 
    hence a reduction of 366 days, for year 0 AD was a leap year 
''' 
ii = datetime.datetime.fromordinal(int(datenum) - 366) 
ff = datetime.timedelta(days=datenum%1) 
return ii + ff 

आशा इस मदद करता है खुश होने के लिए ठीक कर दिया।

1

datetime के बजाय numpy.datetime64 का उपयोग करके इन्हें परिवर्तित करने का एक तरीका यहां दिया गया है।

origin = np.datetime64('0000-01-01', 'D') - np.timedelta64(1, 'D') 
date = serdate * np.timedelta64(1, 'D') + origin 

यह serdate या तो एक पूर्णांक या एक पूर्णांक सरणी के लिए काम करता है।

0

पांडा का उपयोग करना, एक datenum मूल्यों की एक पूरी सरणी, जबकि आंशिक भागों का सम्मान परिवर्तित कर सकते हैं:

import numpy as np 
import pandas as pd 
datenums = np.array([737125, 737124.8, 737124.6, 737124.4, 737124.2, 737124]) 
timestamps = pd.to_datetime(datenums-719529, unit='D') 

मूल्य 719,529 यूनिक्स काल शुरू (1970-01-01) है, जिनमें से datenum मूल्य है pd.to_datetime() के लिए डिफ़ॉल्ट origin

मैं इस सेट अप के लिए निम्न मैटलैब कोड का इस्तेमाल किया:

datenum('1970-01-01') % gives 719529 
datenums = datenum('06-Mar-2018') - linspace(0,1,6) % test data 
datestr(datenums) % human readable format