标记网格中的相邻单元面
Labling neighboring cell faces in a grid
我在 pandas 数据框中有一个节点列表,如下所示:
row col
...
36 182 240
35 182 241
34 182 242
33 182 243
58 183 220
32 183 244
31 183 245
30 183 246
29 183 247
...
这个节点的网格是这样的:
我的代码标记了 X-ed 单元格的每个面,如果它连接到调整 X-ed 单元格,它被标记为 0,如果它没有连接(打开),它被标记为 1。代码在某些方面无法正常工作:
df["Front Face"] = 1
df["Back Face"] = 1
df["Right Face"] = 1
df["Left Face"] = 1
df = df.sort_values(by=['row','col'], ascending=True)
df = df.reset_index(drop=True)
for ix1 in df.index:
try:
if df["col"][ix1] == df["col"][ix1 + 1] - 1:
df["Right Face"][ix1] = 0
df["Left Face"][ix1 + 1] = 0
if df["col"][ix1] == df["col"][ix1 - 1] + 1:
df["Left Face"][ix1] = 0
df["Right Face"][ix1 - 1] = 0
except:
pass
df= df.sort_values(by=['col','row'], ascending=True)
df= df.reset_index(drop=True)
for ix2 in df.index:
try:
if df["row"][ix2] == df["row"][ix2 + 1] - 1:
df["Back Face"][ix2] = 0
df["Front Face"][ix2 + 1] = 0
if df["row"][ix2] == df["row"][ix2 - 1] + 1:
df["Front Face"][ix2] = 0
df["Back Face"][ix2 - 1] = 0
except:
pass
这是输出的一部分,单元格 182,243 和 183,244 缺少一个标签:
row col Front Face Back Face Right Face Left Face
36 182 240 1 1 0 0
35 182 241 1 1 0 0
34 182 242 1 1 0 0
33 182 243 1 0 1 0
58 183 220 1 0 1 1
32 183 244 0 1 0 1
31 183 245 1 1 0 0
30 183 246 1 1 0 0
29 183 247 1 1 0 0
我在这里圈出了图中有问题的单元格:
我假设您 df
中的每一行都标记了一个已占用的位置,并且您想将相邻的单元格标记为前、后、左或右。
如果是这样,您可以用矢量化的方式来做到这一点,但我不得不承认:我费了很大劲才让索引和 numpy 广播正常工作。
# A random 5 * 10 matrix with 10% of rows marked as "occupied"
n, m = 5, 10
count = int(n * m * 0.1)
df = pd.DataFrame({
'row': np.random.randint(n, size=count),
'col': np.random.randint(m, size=count)
}).drop_duplicates()
然后让我们构建 result
数据框:
from itertools import product
# Every row in `df` marks an occupied position
result = df.set_index(['row', 'col']).assign(Occupied = True)
# Now expand `result` into the full matrix
idx = product(range(n), range(m))
result = result.reindex(idx, fill_value=False)
# Every cell is Open initially
for col in ['Front Face', 'Back Face', 'Right Face', 'Left Face']:
result[col] = 1
# Now start to build out a list of blocked cells
occupied = result.query('Occupied').index.to_frame().to_numpy()
valid_index = result.index
faces = {
'Front Face': [-1, 0],
'Back Face': [1, 0],
'Left Face': [0, -1],
'Right Face': [0, 1]
}
for face, offset in faces.items():
blocked = valid_index.intersection([tuple(i) for i in occupied + offset])
result.loc[blocked, face] = 0
为了说明结果,让我们构建一个辅助函数:
from IPython.display import display
def illustrate(result):
display_df = result['Occupied'].map({True: 'x', False: ''}).reset_index()
display_df = display_df.pivot(index='row', columns='col', values='Occupied')
is_open = result[['Front Face', 'Back Face', 'Right Face', 'Left Face']].all(axis=1)
style_df = (
is_open.map({
True: 'background-color: white',
False: 'background-color: rgba(255,0,0,0.2)'
})
.unstack()
)
display(display_df.style.apply(lambda _: style_df, axis=None))
illustrate(result)
结果(红色单元格在 任何 面上有一个 0):
我在 pandas 数据框中有一个节点列表,如下所示:
row col
...
36 182 240
35 182 241
34 182 242
33 182 243
58 183 220
32 183 244
31 183 245
30 183 246
29 183 247
...
这个节点的网格是这样的:
我的代码标记了 X-ed 单元格的每个面,如果它连接到调整 X-ed 单元格,它被标记为 0,如果它没有连接(打开),它被标记为 1。代码在某些方面无法正常工作:
df["Front Face"] = 1
df["Back Face"] = 1
df["Right Face"] = 1
df["Left Face"] = 1
df = df.sort_values(by=['row','col'], ascending=True)
df = df.reset_index(drop=True)
for ix1 in df.index:
try:
if df["col"][ix1] == df["col"][ix1 + 1] - 1:
df["Right Face"][ix1] = 0
df["Left Face"][ix1 + 1] = 0
if df["col"][ix1] == df["col"][ix1 - 1] + 1:
df["Left Face"][ix1] = 0
df["Right Face"][ix1 - 1] = 0
except:
pass
df= df.sort_values(by=['col','row'], ascending=True)
df= df.reset_index(drop=True)
for ix2 in df.index:
try:
if df["row"][ix2] == df["row"][ix2 + 1] - 1:
df["Back Face"][ix2] = 0
df["Front Face"][ix2 + 1] = 0
if df["row"][ix2] == df["row"][ix2 - 1] + 1:
df["Front Face"][ix2] = 0
df["Back Face"][ix2 - 1] = 0
except:
pass
这是输出的一部分,单元格 182,243 和 183,244 缺少一个标签:
row col Front Face Back Face Right Face Left Face
36 182 240 1 1 0 0
35 182 241 1 1 0 0
34 182 242 1 1 0 0
33 182 243 1 0 1 0
58 183 220 1 0 1 1
32 183 244 0 1 0 1
31 183 245 1 1 0 0
30 183 246 1 1 0 0
29 183 247 1 1 0 0
我在这里圈出了图中有问题的单元格:
我假设您 df
中的每一行都标记了一个已占用的位置,并且您想将相邻的单元格标记为前、后、左或右。
如果是这样,您可以用矢量化的方式来做到这一点,但我不得不承认:我费了很大劲才让索引和 numpy 广播正常工作。
# A random 5 * 10 matrix with 10% of rows marked as "occupied"
n, m = 5, 10
count = int(n * m * 0.1)
df = pd.DataFrame({
'row': np.random.randint(n, size=count),
'col': np.random.randint(m, size=count)
}).drop_duplicates()
然后让我们构建 result
数据框:
from itertools import product
# Every row in `df` marks an occupied position
result = df.set_index(['row', 'col']).assign(Occupied = True)
# Now expand `result` into the full matrix
idx = product(range(n), range(m))
result = result.reindex(idx, fill_value=False)
# Every cell is Open initially
for col in ['Front Face', 'Back Face', 'Right Face', 'Left Face']:
result[col] = 1
# Now start to build out a list of blocked cells
occupied = result.query('Occupied').index.to_frame().to_numpy()
valid_index = result.index
faces = {
'Front Face': [-1, 0],
'Back Face': [1, 0],
'Left Face': [0, -1],
'Right Face': [0, 1]
}
for face, offset in faces.items():
blocked = valid_index.intersection([tuple(i) for i in occupied + offset])
result.loc[blocked, face] = 0
为了说明结果,让我们构建一个辅助函数:
from IPython.display import display
def illustrate(result):
display_df = result['Occupied'].map({True: 'x', False: ''}).reset_index()
display_df = display_df.pivot(index='row', columns='col', values='Occupied')
is_open = result[['Front Face', 'Back Face', 'Right Face', 'Left Face']].all(axis=1)
style_df = (
is_open.map({
True: 'background-color: white',
False: 'background-color: rgba(255,0,0,0.2)'
})
.unstack()
)
display(display_df.style.apply(lambda _: style_df, axis=None))
illustrate(result)
结果(红色单元格在 任何 面上有一个 0):