1
2 """Extended version of the Pandas-Dataframe
3 """
4
5 from pandas import DataFrame,Series
6 from numpy import hstack,unique
7 from math import isnan
8
9 from PyFoam.Error import error,warning,PyFoamException
10
11 from PyFoam.ThirdParty.six import string_types,text_type,u
12
14 """This class adds some convenience functions to the regular Datafram class"""
15
16 validOtherTypes=(DataFrame,Series)
17
23
24
25
26
27
32
33 - def addData(self,other,
34 sameIndex=True,
35 mergeIndex=False,
36 prefix=None,
37 suffix=None,
38 allowExtrapolate=False,
39 interpolationMethod="values"):
40 """Add data from another DataFrame or Series
41 @param other: data as Pandas-DataFrame or Series
42 @param sameIndex: assum both have the same indices. If False the other data will be interpolated to the current indices
43 @param mergeIndex: make the result indices a mixture of the indices"""
44 if not sameIndex and mergeIndex:
45 raise PandasWrapperPyFoamException("Can't specify sameIndex=False and mergeIndex=True at the same time")
46 if not isinstance(other,self.validOtherTypes):
47 raise PandasWrapperPyFoamException("Other data is of type",type(other),
48 "should be one of",self.validOtherTypes)
49 if isinstance(other,DataFrame):
50 o=other
51 else:
52 o=DataFrame(other)
53
54 k=o.keys()
55 if not self.__allStrings(k):
56 raise PandasWrapperPyFoamException("Added data with non-string columns")
57 v=k.copy()
58 if prefix:
59 v=[prefix+n for n in v]
60 if suffix:
61 v=[n+suffix for n in v]
62 if len(set(v)&set(self.keys()))>0:
63 raise PandasWrapperPyFoamException("Keys of this",self.keys(),"and other",v,
64 "intersect",set(v)&set(self.keys()))
65 keys=dict(zip(k,v))
66 interpolate=False
67 if len(self.index)!=len(o.index) or (self.index!=o.index).any():
68 if sameIndex and not mergeIndex:
69 raise PandasWrapperPyFoamException("Other data has different index. Specify sameIndex=False or mergeIndex=True")
70 ni=unique(hstack([self.index,o.index]))
71 interpolate=True
72 if mergeIndex:
73 minOld=min(self.index)
74 maxOld=max(self.index)
75
76 result=self.reindex(index=ni,copy=True).interpolate(
77 method=interpolationMethod,limit=1)
78
79 if not allowExtrapolate:
80 for s in result:
81 result[s][result.index<minOld]=float("NaN")
82 result[s][result.index>maxOld]=float("NaN")
83 else:
84
85
86 o=o.reindex(index=ni,columns=o.columns).interpolate(method=interpolationMethod)
87
88 result=self.copy()
89 else:
90 result=self.copy()
91
92 minOld=min(o.index)
93 maxOld=max(o.index)
94 for k,v in keys.items():
95 result[v]=o[k]
96 if interpolate:
97 result[v]=result[v].interpolate(method=interpolationMethod,limit=1)
98 if not allowExtrapolate:
99 result[v][result.index<minOld]=float("NaN")
100 result[v][result.index>maxOld]=float("NaN")
101
102 return PyFoamDataFrame(result)
103
105 """Integrate by using the trapezoid rule. Return a dictionary with values.
106 @param values: list of column names. If unset all are integrated"""
107 return self.__integrateInternal(columns)[0]
108
110 """Length were the values are valid (not NaN) Return a dictionary with values.
111 @param values: list of column names. If unset all are integrated"""
112 return self.__integrateInternal(columns)[1]
113
115 """Weighted average. Return a dictionary with values.
116 @param values: list of column names. If unset all are integrated"""
117 integral,length=self.__integrateInternal(columns)
118 result={}
119 for k in integral:
120 if length[k]>0 and not isnan(length[k]):
121 result[k]=integral[k]/length[k]
122 else:
123 result[k]=float("NaN")
124 return result
125
127 if columns is None:
128 columns=self.keys()
129 integrals={}
130 lengths={}
131 ind=self.index
132
133 for k in columns:
134 integrals[k]=0
135 lengths[k]=0
136 if len(ind)<2:
137 integrals[k]=float("NaN")
138 continue
139 val=self[k].values
140 for i in range(len(ind)):
141 if not isnan(val[i]):
142 w=0
143 if i>0:
144 w+=0.5*(ind[i]-ind[i-1])
145 if i+1<len(ind):
146 w+=0.5*(ind[i+1]-ind[i])
147 lengths[k]+=w
148 integrals[k]+=w*val[i]
149 if lengths[k]==0:
150 integrals[k]=float("NaN")
151
152 return integrals,lengths
153
155 """Adds our own statistics to the regular describe"""
156 d=super(PyFoamDataFrame,self).describe(*args,**kwargs)
157 integral,length=self.__integrateInternal(self.keys())
158 d=d.append(DataFrame(data=integral,index=["integral"]))
159 d=d.append(DataFrame(data=length,index=["valid length"]))
160 a={}
161 for k in integral:
162 if length[k]>0 and not isnan(length[k]):
163 a[k]=integral[k]/length[k]
164 else:
165 a[k]=float("NaN")
166 d=d.append(DataFrame(data=a,index=["weighted average"]))
167 return d
168
170 """The PyFoam-exception that does not expect to be caught"""
171
176