<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Again, first of all, lets read some data
Read some wind data
Step1:  Selecting data
Access the elements like if it was a numpy array
We can access the elements using indexing like if it was a numpy array or how we do it in Python
Step2:  Indexes in a numpy array can only be integers.
Access the elements through indexing the labels of the index
Also, unlike numpy, we can access indexes that are not integers
Step3:  In this second example indexing is made using strings, that are the representation on the indexes (labels). We can also highlight that, in this case, the last element in the slice IS INCLUDED.
Basic selection of a column (DataFrame)
In previous examples, we havel also seen that we could select columns using its name
Step4:  Depending how are defined the column names we can access the column values using dot notation but this way not always work so I strongly recommend not to use it
Step5:  Fancy indexing with Series
You can also use Fancy indexing with Series, like if we were indexing with a list or a boolean array
Step6:  With DataFrames the fancy indexing can be ambiguous and it will raise an IndexError.
Step7:  Boolean indexing
Like with numpy, we can access values using boolean indexing
Step8:  We can use several conditions. for instance, let's refine the previous result
Step9:  Using conditions coud be less readable. Since version 0.13 you can use the query method to make the expression more readable.
Step10:  Using these ways of selection can be ambiguous in some cases. Let's make a parenthetical remark to come bacllater to see more advanced ways of selection.
Remark
Step11:  Now, if we perform an operation between both Series, where there are the same index we can perform the operation and where there are no indexes on both sides of the operation we conserve the index in the result but the operation could not be performed and a NaN is returned but we will not get an error
Step12:  Coming back to indexing (recap)
One of the basic features of pandas is the rows and columns index labeling, this can make that indexing could be more complex than in numpy. We have to distinguish between
Step13:  Or we can select several columns
Step14:  But with slicing we will access the indexes
Step15:  So the following will provide an error
Step16:  Uh, what a mess!!
Indexing (à la pandas)
We have several available methods to index in a pandas data structure
Step17:  A fourth way not seen before would be
Step18:  Let's practice all of this
Return all the January 2014 values
Compute the mean wind speed during february 2014
Use the query method to obtain all wind speeds coming from North (in a range between $\pm$ 10 º considering North oriented towards North 0º) and with a wind speed above 10 m/s
The same as before but using a boolean array
All the previous problems can be solved loc, iloc and/or ix. Practice all the possibilities.
Last curiosity in case you work with time series
pandas data structures have a method to select between times
<ASSISTANT_TASK:>
Python Code:
# first, the imports
import os
import datetime as dt
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import display
np.random.seed(19760812)
%matplotlib inline
# We read the data in the file 'mast.txt'
ipath = os.path.join('Datos', 'mast.txt')
def dateparse(date, time):
    YY = 2000 + int(date[:2])
    MM = int(date[2:4])
    DD = int(date[4:])
    hh = int(time[:2])
    mm = int(time[2:])
    
    return dt.datetime(YY, MM, DD, hh, mm, 0)
    
cols = ['Date', 'time', 'wspd', 'wspd_max', 'wdir',
        'x1', 'x2', 'x3', 'x4', 'x5', 
        'wspd_std']
wind = pd.read_csv(ipath, sep = "\s*", names = cols, 
                   parse_dates = [[0, 1]], index_col = 0,
                   date_parser = dateparse)
Explanation: Again, first of all, lets read some data
Read some wind data
End of explanation
wind[0:10]
Explanation: Selecting data
Access the elements like if it was a numpy array
We can access the elements using indexing like if it was a numpy array or how we do it in Python:
In Python, indexing starts by 0 and the last element of the slice is not included.
End of explanation
wind['2013-09-04 00:00:00':'2013-09-04 01:30:00']
Explanation: Indexes in a numpy array can only be integers.
Access the elements through indexing the labels of the index
Also, unlike numpy, we can access indexes that are not integers:
End of explanation
wind['wspd'].head(3)
Explanation: In this second example indexing is made using strings, that are the representation on the indexes (labels). We can also highlight that, in this case, the last element in the slice IS INCLUDED.
Basic selection of a column (DataFrame)
In previous examples, we havel also seen that we could select columns using its name:
End of explanation
# Thi is similar to what we did in the previous code cell
wind.wspd.head(3)
# An example that can raise an error
df1 = pd.DataFrame(np.random.randn(5,2), columns = [1, 2])
df1
# This will be wrong
df1.1
# In order to use it we have to use
df1[1]
Explanation: Depending how are defined the column names we can access the column values using dot notation but this way not always work so I strongly recommend not to use it:
End of explanation
# Create a Series
wspd = wind['wspd']
# Access the elements located at positions 0, 100 and 1000
print(wspd[[0, 100, 1000]])
print('\n' * 3)
# Using indexes at locations 0, 100 and 1000
idx = wspd[[0, 100, 1000]].index
print(idx)
print('\n' * 3)
# We access the same elements than initially but using the labels instead 
# the location of the elements
print(wspd[idx])
Explanation: Fancy indexing with Series
You can also use Fancy indexing with Series, like if we were indexing with a list or a boolean array:
End of explanation
# Try it...
Explanation: With DataFrames the fancy indexing can be ambiguous and it will raise an IndexError.
End of explanation
idx = wind['wspd'] > 35
wind[idx]
Explanation: Boolean indexing
Like with numpy, we can access values using boolean indexing:
End of explanation
idx = (wind['wspd'] > 35) & (wind['wdir'] > 225)
wind[idx]
Explanation: We can use several conditions. for instance, let's refine the previous result:
End of explanation
# To make it more efficient you should install 'numexpr'
# tht is the default engine. If you don't have it installed
# and you don't define the engine ('python') you will get an ImportError
wind.query('wspd > 35 and wdir > 225', engine = 'python')
Explanation: Using conditions coud be less readable. Since version 0.13 you can use the query method to make the expression more readable.
End of explanation
s1 = pd.Series(np.arange(0,10), index = np.arange(0,10))
s2 = pd.Series(np.arange(10,20), index = np.arange(5,15))
print(s1)
print(s2)
Explanation: Using these ways of selection can be ambiguous in some cases. Let's make a parenthetical remark to come bacllater to see more advanced ways of selection.
Remark: Aligment of data when we operate with pandas data structures
When we perform an operation between two pandas data structures we get a very practical alignment effect. Let's see this by examples:
End of explanation
s1 + s2
Explanation: Now, if we perform an operation between both Series, where there are the same index we can perform the operation and where there are no indexes on both sides of the operation we conserve the index in the result but the operation could not be performed and a NaN is returned but we will not get an error:
End of explanation
wind['wspd_std']
Explanation: Coming back to indexing (recap)
One of the basic features of pandas is the rows and columns index labeling, this can make that indexing could be more complex than in numpy. We have to distinguish between:
selecting by label
selecting by position (numpy)
Indexing in Series is simpler as the labels refer to row labels (indexes) as there is only one column. As we have been learning in a vague manner, for a DataFrame, basic indexing select columns.
To select only a column, as we have seen previously:
End of explanation
wind[['wspd', 'wspd_std']]
Explanation: Or we can select several columns:
End of explanation
wind['2015/01/01 00:00':'2015/01/01 02:00']
Explanation: But with slicing we will access the indexes:
End of explanation
wind['wspd':'wdir']
wind[['wspd':'wdir']]
Explanation: So the following will provide an error:
End of explanation
wind.loc['2013-09-04 00:00:00':'2013-09-04 00:20:00', 'wspd':'wspd_max']
wind.iloc[0:3, 0:2] # similar to indexing a numpy arrays wind.values[0:3, 0:2]
wind.ix[0:3, 'wspd':'wspd_max']
Explanation: Uh, what a mess!!
Indexing (à la pandas)
We have several available methods to index in a pandas data structure:
loc: it is used when we use the columns and rows labels to index (it also accepts boolean arrays).
iloc: this option is based in element positions (like if it was a numpy array).
ix: it is a combination of both previous methods.
This methods are also available in Series but with Series are not so useful as indexing is not ambiguous.
Let's see how these methods work in a DataFrame...
Select the first three items in columns 'wspd' and 'wspd_max':
End of explanation
wind[0:3][['wspd', 'wspd_max']]
wind[['wspd', 'wspd_max']][0:3]
Explanation: A fourth way not seen before would be:
End of explanation
wind.between_time('00:00', '00:30').head(20)
# It also works with series:
wind['wspd'].between_time('00:00', '00:30').head(20)
Explanation: Let's practice all of this
Return all the January 2014 values
Compute the mean wind speed during february 2014
Use the query method to obtain all wind speeds coming from North (in a range between $\pm$ 10 º considering North oriented towards North 0º) and with a wind speed above 10 m/s
The same as before but using a boolean array
All the previous problems can be solved loc, iloc and/or ix. Practice all the possibilities.
Last curiosity in case you work with time series
pandas data structures have a method to select between times:
End of explanation
<END_TASK>