【发布时间】:2018-09-30 13:23:08
【问题描述】:
需要帮助根据两个振荡值的条件将不同的状态标记到新的数据框列中; X & Y 列。
使用 Y 列作为状态区间。状态间隔从 0 开始,到 0 结束。请注意 Y 列中的值将始终保持在正或负范围内。每个间隔循环将按顺序依次为+、-、+、-等。
当 Y 列的值变为大于 0 的正数时开始标记,并在变为负数之前在 0 处停止;是循环的结束,将开始下一个范围或进入负范围的循环。
共有 6 种模式:A、B、C、D、E、F 作为循环状态。我试图弄清楚逻辑以及如何将每个状态的标签添加到名为 state 的新数据框列中。标记针对每个周期进行,并在每个新的周期状态重新开始。
+-------+-------------+---------+
| State | X | Y |
+-------+-------------+---------+
| A | from - to + | + |
| B | + | + |
| C | - | + |
| D | + | - |
| E | - | - |
| F | from + to - | - |
+-------+-------------+---------+
对于状态 A 和 F,(X 列)的值从 + 变为 -,反之亦然,交叉超过 0。Y 列中的值将始终保持在正值或负值范围内。
国家 B、C、D、E 在(X 列)中没有交叉。以下是示例数据框值和具有结果状态的示例新列。
+----+---------+---------+-------+
| # | X | Y | State |
+----+---------+---------+-------+
| 1 | -0.0034 | 0.0056 | A | Cycle 1 (+)
| 2 | -0.0001 | 0.0070 | A |
| 3 | 0.0019 | 0.0073 | A |
| 4 | 0.0039 | 0.0075 | A |
| | | | |
| 5 | 0.0273 | -0.0037 | D | Cycle 2 (-)
| 6 | 0.0237 | -0.0059 | D |
| | | | |
| 7 | 0.0047 | 0.0028 | B | Cycle 3 (+)
| 8 | 0.0044 | 0.0020 | B |
| | | | |
| 9 | -0.0034 | -0.0006 | E | Cycle 4 (-)
| 10 | -0.0045 | -0.0014 | E |
| | | | |
| 11 | -0.0021 | 0.0006 | C | Cycle 5 (+)
| 12 | -0.0019 | 0.0007 | C |
| | | | |
| 13 | 0.0041 | -0.0054 | F | Cycle 6 (-)
| 14 | 0.0017 | -0.0060 | F |
| 15 | -0.0021 | -0.0059 | F |
| 16 | -0.0023 | -0.0057 | F |
+----+---------+---------+-------+
Cycles will continue 7, 8, 9, 10, etc. in the time series
具有 12 个周期的 DataFrame,类似于上面的示例,在结果中显示了 A、B、C、D、E、F 中的每个模式两次。
df = pd.DataFrame({
'x': [-0.0034, -0.0001, 0.0019, 0.0039, 0.0273, 0.0237, 0.0047, 0.0044, -0.0034, -0.0045, -0.0021, -0.0019, 0.0041, 0.0017, -0.0021, -0.0023, -0.0014, -0.0002, 0.0018, 0.0031, 0.0171, 0.0230, 0.0035, 0.0040, -0.0030, -0.0040, -0.0020, -0.0015, 0.0030, 0.0010, -0.0030, -0.0020, ],
'y': [0.0056, 0.007, 0.0073, 0.0075, -0.0037, -0.0059, 0.0028, 0.002, -0.0006, -0.0014, 0.0006, 0.0007, -0.0054, -0.006, -0.0059, -0.0057, 0.0040, 0.005, 0.0065, 0.0070, -0.0022, -0.0045, 0.0020, 0.001, -0.0005, -0.0010, 0.0003, 0.0005, -0.0050, -0.005, -0.0060, -0.0040, ],
})
接下来是开始编写遍历数据帧的示例,需要帮助构建逻辑、合并 A 和 F 状态、遍历每个 +/- 循环以及如何遍历 Y 列以查找 X 列中的交叉值的指导.
State = []
for i, row in df.iterrows(): #i: dataframe index; row: each row in series format
if row['X'] > 0 and row['Y'] > 0:
State.append('B')
elif row['X'] < 0 and row['Y'] > 0:
State.append('C')
elif row['X'] > 0 and row['Y'] < 0:
State.append('D')
elif row['X'] < 0 and row['Y'] < 0:
State.append('E')
else:
State.append('err')
df['State'] = State
print(df)
同样,上面的代码没有包含 A & F 状态。
更新
仍然需要帮助,下面是使用 cmets 更新的代码,并将解释什么不起作用。
# Creating new column as + or - based on Column Y value
df['y_pos'] = np.where((df.y > 0), True, False)
# Creating new column to label the cycle as they are increasing order 1,2,3, etc.
df['cycle_n'] = (df.y_pos != df.y_pos.shift(1)).cumsum()
# returns dictionary whose keys and values are from DataFrames
# to be able to loop through the cycles
gb = df.groupby('cycle_n')
groups = dict(list(gb))
State = []
for name, group in gb:
# Information to help compare our final results
print("Group:" + str(name) )
print("=====================")
print("Min:" + str(group.min()) )
print("Max:" + str(group.max()) )
print("--- Group Data -----")
print(group)
print("--------------------")
print("--- Column X Row Data -----")
for index, row in group.iterrows(): # loop each row
if row['y_pos'] == True: # Column Y is (+)
print( row['x'] ) # row data value for Column X
# trying to use min and max in each cycle to figure out
# if there is a crossover
# ISSUE: min and max is holding data values for each of the
# columns, not only Column X which maybe the reason why
# it's not working correctly
if [ (group.min() <= 0) & (group.max() >= 0) ]:
State.append('A')
elif row['x'] >= 0:
State.append('B')
elif row['x'] < 0:
State.append('C')
else:
State.append('err')
elif row['y_pos'] == False: # Column Y is (-)
print( row['x'] )
# ISSUE: again min and max is holding data values for each of the
# columns, maybe the reason why it's not working correctly
if [ (group.max() >= 0) & (group.min() <= 0) ]:
State.append('F')
elif row['x'] >= 0:
State.append('D')
elif row['x'] < 0:
State.append('E')
else:
State.append('err')
else:
print("err")
df['State'] = State
# Combining y_pos & cycle_n to be printed out.
df['Label'] = 'Cycle ' + df.cycle_n.astype(str) + ' ' + df.y_pos.map({True: '(+)', False: '(-)'})
del df['y_pos']
del df['cycle_n']
print(df)
此代码有问题。它现在只标记状态 A 和 F,并将其他状态错误标记为 A 或 F。使用 min 和 max 的 If 语句返回 true;真的不正确,因为它保存了字典中所有列 mins 和 max 的值。例如,
print("Min:" + str(group.min()) )
Min:
x -0.0034
y 0.0056
y_pos 1.0000
cycle_n 1.0000
dtype: float64
不知道这是否是最好的方法,只是越来越接近它可以正常工作。
【问题讨论】:
-
如果您可以提供一个示例数据框,他们可以粘贴到他们自己的代码中,那么人们会更容易回答您的问题。
-
几个后续问题 - 当您的字母用完时(即在
Z之后),您希望发生什么?此外,您是否有理由需要跟踪df.X正在做什么?看起来您只需根据df.Y更新标签就可以逃脱惩罚。
标签: python pandas loops dataframe iterator