Python pandas pyhaystack
Python pandas pyhaystack
我正在使用一个名为 pyhaystack 的模块从基于 'tags.' Python 的楼宇自动化系统检索数据 (rest API) 将 return 的字典数据。我正在尝试将 pandas 与下面的 If Else 语句一起使用,但我遇到了问题。 pyhaystack 可以很好地获取数据...
这将我连接到自动化系统:(工作正常)
from pyhaystack.client.niagara import NiagaraHaystackSession
import pandas as pd
session = NiagaraHaystackSession(uri='http://0.0.0.0', username='Z', password='z', pint=True)
此代码找到名为 'znt' 的标签,将字典转换为 Pandas,并过滤时间:(对这两个点工作得很好)
znt = session.find_entity(filter_expr='znt').result
znt = session.his_read_frame(znt, rng= '2018-01-01,2018-02-12').result
znt = pd.DataFrame.from_dict(znt)
znt.index.names=['Date']
znt = znt.fillna(method = 'ffill').fillna(method = 'bfill').between_time('08:00','17:00')
我最感兴趣的是列名,最终我想要Python到return根据条件命名的列:
print(znt.columns)
print(znt.values)
Returns:
Index(['C.Drivers.NiagaraNetwork.Adams_Friendship.points.A-Section.AV1.AV1ZN~2dT', 'C.Drivers.NiagaraNetwork.points.A-Section.AV2.AV2ZN~2dT'], dtype='object')
[[ 65.9087 66.1592]
[ 65.9079 66.1592]
[ 65.9079 66.1742]
...,
[ 69.6563 70.0198]
[ 69.6563 70.2873]
[ 69.5673 70.2873]]
我对 Pandas 数据框的这个名称最感兴趣。 C.Drivers.NiagaraNetwork.Adams_Friendship.points.A-Section.AV1.AV1ZN~2dT
对于我的两个数组,我为数据框中的数据减去 70 的值。 (工作正常)
znt_sp = 70
deviation = znt - znt_sp
deviation = deviation.abs()
deviation
这就是我在 Pandas 中被绊倒的地方。如果偏差大于四,我希望 Python 打印列的名称,否则打印此区域为正常。任何提示将不胜感激..
if (deviation > 4).any():
print('Zone %f does not make setpoint' % deviation)
else:
print('Zone %f is Normal' % deviation)
Pandas 中的列名称是:
C.Drivers.NiagaraNetwork.Adams_Friendship.points.A-Section.AV1.AV1ZN~2dT
解法:
您可以遍历 columns
for col in df.columns:
if (df[col] > 4).any(): # or .all if needed
print('Zone %s does not make setpoint' % col)
else:
print('Zone %s is Normal' % col)
或者定义一个函数并使用apply
def _print(x):
if (x > 4).any():
print('Zone %s does not make setpoint' % x.name)
else:
print('Zone %s is Normal' % x.name)
df.apply(lambda x: _print(x))
# you can even do
[_print(df[col]) for col in df.columns]
建议:
也许你会将结果保存在另一个结构中,将函数更改为 return 一个布尔系列 "is normal":
def is_normal(x):
return not (x > 4).any()
s = df.apply(lambda x: is_normal(x))
# or directly
s = df.apply(lambda x: not (x > 4).any())
它将 return 一个系列 s
其中 index
是您的 df
的列名, values
是一个与您的条件相对应的布尔值。
然后您可以使用它来获取所有 Normal 列名称 s[s].index
或 non-normal s[~s].index
例如:我只想要 df 的普通列:df[s[s].index]
一个完整的例子
例如,我将使用条件与您不同的样本 df
(我检查是否没有元素低于 4 - 正常,否则不设定设定值)
df = pd.DataFrame(dict(a=[1,2,3],b=[2,3,4],c=[3,4,5])) # A sample
print(df)
a b c
0 1 2 3
1 2 3 4
2 3 4 5
你的用例:打印是否正常 - 解决方案
for col in df.columns:
if (df[col] < 4).any():
print('Zone %s does not make setpoint' % col)
else:
print('Zone %s is Normal' % col)
结果
Zone a is Normal
Zone b is does not make setpoint
Zone c is does not make setpoint
举例说明我的建议:将is_normal
列保持在一个系列中
s = df.apply(lambda x: not (x < 4).any()) # Build the series
print(s)
a True
b False
c False
dtype: bool
print(df[s[~s].index]) #Falsecolumns df
b c
0 2 3
1 3 4
2 4 5
print(df[s[s].index]) #Truecolumns df
a
0 1
1 2
2 3
我认为 DataFrame 是处理您想要的内容的好方法。
从 znt 开始,您可以在那里进行所有计算:
deviation = znt - 70
deviation = deviation.abs()
# and the cool part is filtering in the df
problem_zones =
deviation[deviation['C.Drivers.NiagaraNetwork.Adams_Friendship.points.A-
Section.AV1.AV1ZN~2dT']>4]
您可以玩这个并想出一种遍历列的方法,例如:
for each in df.columns:
# if in this column, more than 10 occurences of deviation GT 4...
if len(df[df[each]>4]) > 10:
print('This zone have a lot of troubles : ', each)
编辑
我喜欢向 DataFrame 添加列,而不是仅仅构建一个外部系列。
df[‘error_for_a’] = df[a] - 70
这打开了可能性并将所有内容放在一起。可以使用
df[df[‘error_for_a’]>4]
同样,all() 或 any() 可能很有用,但在现实生活中,当出现一定数量的错误时,我们可能需要触发“故障检测”。
如果日程安排在上午 8 点设置为“占用”....也许第一个条目不正确....(即使情况在 30 分钟后好转,任何条目都会触发错误)。另一种情况是一个错误很小的会议室......但是一旦有人在里面......事情就会变糟(all()不会看到)。
我正在使用一个名为 pyhaystack 的模块从基于 'tags.' Python 的楼宇自动化系统检索数据 (rest API) 将 return 的字典数据。我正在尝试将 pandas 与下面的 If Else 语句一起使用,但我遇到了问题。 pyhaystack 可以很好地获取数据...
这将我连接到自动化系统:(工作正常)
from pyhaystack.client.niagara import NiagaraHaystackSession
import pandas as pd
session = NiagaraHaystackSession(uri='http://0.0.0.0', username='Z', password='z', pint=True)
此代码找到名为 'znt' 的标签,将字典转换为 Pandas,并过滤时间:(对这两个点工作得很好)
znt = session.find_entity(filter_expr='znt').result
znt = session.his_read_frame(znt, rng= '2018-01-01,2018-02-12').result
znt = pd.DataFrame.from_dict(znt)
znt.index.names=['Date']
znt = znt.fillna(method = 'ffill').fillna(method = 'bfill').between_time('08:00','17:00')
我最感兴趣的是列名,最终我想要Python到return根据条件命名的列:
print(znt.columns)
print(znt.values)
Returns:
Index(['C.Drivers.NiagaraNetwork.Adams_Friendship.points.A-Section.AV1.AV1ZN~2dT', 'C.Drivers.NiagaraNetwork.points.A-Section.AV2.AV2ZN~2dT'], dtype='object')
[[ 65.9087 66.1592]
[ 65.9079 66.1592]
[ 65.9079 66.1742]
...,
[ 69.6563 70.0198]
[ 69.6563 70.2873]
[ 69.5673 70.2873]]
我对 Pandas 数据框的这个名称最感兴趣。 C.Drivers.NiagaraNetwork.Adams_Friendship.points.A-Section.AV1.AV1ZN~2dT
对于我的两个数组,我为数据框中的数据减去 70 的值。 (工作正常)
znt_sp = 70
deviation = znt - znt_sp
deviation = deviation.abs()
deviation
这就是我在 Pandas 中被绊倒的地方。如果偏差大于四,我希望 Python 打印列的名称,否则打印此区域为正常。任何提示将不胜感激..
if (deviation > 4).any():
print('Zone %f does not make setpoint' % deviation)
else:
print('Zone %f is Normal' % deviation)
Pandas 中的列名称是: C.Drivers.NiagaraNetwork.Adams_Friendship.points.A-Section.AV1.AV1ZN~2dT
解法:
您可以遍历 columns
for col in df.columns:
if (df[col] > 4).any(): # or .all if needed
print('Zone %s does not make setpoint' % col)
else:
print('Zone %s is Normal' % col)
或者定义一个函数并使用apply
def _print(x):
if (x > 4).any():
print('Zone %s does not make setpoint' % x.name)
else:
print('Zone %s is Normal' % x.name)
df.apply(lambda x: _print(x))
# you can even do
[_print(df[col]) for col in df.columns]
建议: 也许你会将结果保存在另一个结构中,将函数更改为 return 一个布尔系列 "is normal":
def is_normal(x):
return not (x > 4).any()
s = df.apply(lambda x: is_normal(x))
# or directly
s = df.apply(lambda x: not (x > 4).any())
它将 return 一个系列 s
其中 index
是您的 df
的列名, values
是一个与您的条件相对应的布尔值。
然后您可以使用它来获取所有 Normal 列名称 s[s].index
或 non-normal s[~s].index
例如:我只想要 df 的普通列:df[s[s].index]
一个完整的例子
例如,我将使用条件与您不同的样本 df
(我检查是否没有元素低于 4 - 正常,否则不设定设定值)
df = pd.DataFrame(dict(a=[1,2,3],b=[2,3,4],c=[3,4,5])) # A sample
print(df)
a b c
0 1 2 3
1 2 3 4
2 3 4 5
你的用例:打印是否正常 - 解决方案
for col in df.columns:
if (df[col] < 4).any():
print('Zone %s does not make setpoint' % col)
else:
print('Zone %s is Normal' % col)
结果
Zone a is Normal
Zone b is does not make setpoint
Zone c is does not make setpoint
举例说明我的建议:将is_normal
列保持在一个系列中
s = df.apply(lambda x: not (x < 4).any()) # Build the series
print(s)
a True
b False
c False
dtype: bool
print(df[s[~s].index]) #Falsecolumns df
b c
0 2 3
1 3 4
2 4 5
print(df[s[s].index]) #Truecolumns df
a
0 1
1 2
2 3
我认为 DataFrame 是处理您想要的内容的好方法。 从 znt 开始,您可以在那里进行所有计算:
deviation = znt - 70
deviation = deviation.abs()
# and the cool part is filtering in the df
problem_zones =
deviation[deviation['C.Drivers.NiagaraNetwork.Adams_Friendship.points.A-
Section.AV1.AV1ZN~2dT']>4]
您可以玩这个并想出一种遍历列的方法,例如:
for each in df.columns:
# if in this column, more than 10 occurences of deviation GT 4...
if len(df[df[each]>4]) > 10:
print('This zone have a lot of troubles : ', each)
编辑
我喜欢向 DataFrame 添加列,而不是仅仅构建一个外部系列。
df[‘error_for_a’] = df[a] - 70
这打开了可能性并将所有内容放在一起。可以使用
df[df[‘error_for_a’]>4]
同样,all() 或 any() 可能很有用,但在现实生活中,当出现一定数量的错误时,我们可能需要触发“故障检测”。
如果日程安排在上午 8 点设置为“占用”....也许第一个条目不正确....(即使情况在 30 分钟后好转,任何条目都会触发错误)。另一种情况是一个错误很小的会议室......但是一旦有人在里面......事情就会变糟(all()不会看到)。