检查元素是否是邻居,然后创建一个新列
check if an element is a neighbor and then create a new column
我有一个数据框,它由五列“ID”、“Name”、“pos_x”、“pos_y”和“Volume”组成,如下所示:
ID | Name | pos_x | pos_y | volume
1 | A | 1 | 1.5 | 10
2 | A | 3.5 | 3 | 6
3 | A | 4 | 4 | 8
4 | A | 4.5 | 4.5 | 9
5 | A | 5 | 6 | 10
1 | B | 1.2 | 1.2 | 4
3 | B | 4.3 | 4.4 | 8
4 | B | 4.5 | 4.2 | 7
2 | C | 3 | 3.3 | 9
3 | C | 4.2 | 4.1 | 10
我现在想在数据框 ("volume_avg") 中创建一个新列,其中计算所有 ID 的体积的平均值,其半径在 2.5 毫米到各自的ID。
我的想法是先运行遍历每个名字的每个ID(因为名字+ID是主键)然后看每个ID的位置x和y。使用 if 循环,然后我将检查 ID 是否是邻居。
所以条件是:
if pos_x(当前 ID)< pos_x(所有其他 ID)- 2.5 或 > pos_x(所有其他 ID)+ 2.5
else if pos_y(当前 ID)< pos_y(所有其他 ID)- 2.5 或 > pos_y(所有其他 ID)+ 2.5
然后计算 sum(volume)/count(ID's)
否则什么都没有
不幸的是,我不知道如何在 python 代码中写下这些注意事项....
如果你能帮助我,我会很高兴。非常感谢。
大卫
我将 if 和 else 部分中的条件解释为 (x,y)
坐标上的矩形限制。如果这不正确,请告诉我,我可以调整 if/else.
中的逻辑
import pandas as pd
# create the structure of example dataframe
df = pd.DataFrame([[1, 'A', 1, 1.5, 10],
[2, 'A', 3.5, 3, 6],
[3, 'A', 4, 4, 8],
[4, 'A', 4.5, 4.5, 9],
[5 ,'A' , 5 , 6 , 10],
[1 ,'B' , 1.2 , 1.2 , 4],
[3 ,'B' , 4.3 , 4.4 , 8],
[4 ,'B' , 4.5 , 4.2 , 7],
[2 ,'C' , 3 , 3.3 , 9],
[3 ,'C' , 4.2 , 4.1 , 10],
],
columns=['ID', 'Name', 'pos_x', 'pos_y', 'volume'])
# create volume average with rows that meet criterion
volume_avgs = []
for g, grouper in df.groupby('Name'):
for base_row in grouper.iterrows():
v_sum = 0
v_count = 0
for row in grouper.iterrows():
if row[1].ID == base_row[1].ID: # skip the item itself
continue
elif abs(row[1].pos_x - base_row[1].pos_x) < 2.5 or abs(row[1].pos_y - base_row[1].pos_y) < 2.5:
v_sum += row[1].volume
v_count += 1
volume_avgs.append([base_row[1].ID, g, v_sum / v_count if v_count > 0 else 0, v_count])
df_vol_avgs = pd.DataFrame(volume_avgs, columns=['ID', 'Name', 'volume_avg', 'volume_count'])
merged_df = df.merge(df_vol_avgs, on=['ID', 'Name'])
merged_df
请注意,如果实际数据很大,这可能不会很好地扩展。由于双 for 循环,特别是对于具有大量数据的组。此外,如果您想要 None
或 Nan
如果附近的平均点总数为 0,您可以将 if/else 从
更改为
v_sum / v_count if v_count > 0 else 0
到
v_sum / v_count if v_count > 0 else None
对于 None
的情况和 Nan
的情况类似,比如使用 numpy.nan
。
我找到了一种可行的方法,但它不是最干净的方法,可能可以通过多种方式进行优化。
首先,我们导入 pandas 并创建数据框:
import pandas as pd
ID = [1,2,3,4,5,1,3,4,2,3]
name = ["A","A","A","A","A","B","B","B","C","C"]
pos_x = [1,3.5,4,4.5,5,1.2,4.3,4.5,3,4.2]
pos_y = [1.5,3,4,4.5,6,1.2,4.4,4.2,3.3,4.1]
volume = [10,6,8,9,10,4,8,7,9,10]
dict = {"ID": ID, "name": name, "pos_x":pos_x, "pos_y":pos_y,"volume":volume}
df = pd.DataFrame(dict)
然后,我们声明一个空列表来存储我们的结果并迭代数据框:
values = []
for i in df.itertuples():
posX = i.pos_x
posY = i.pos_y
counter = 0
volume_counter = 0
for j in df.itertuples():
if i == j:
pass
elif abs(j.pos_x - posX) <= 2.5 and abs(j.pos_y - posY) <= 2.5:
counter += 1
volume_counter += j.volume
else:
pass
values.append(round(volume_counter/counter,2))
对于数据框的每一行,我们得到 x 和 y 位置。我们也将counter和volume_counter设置为0。Counter统计有多少物品满足距离其他位置2.5mm以内的条件,volume_counter将满足条件的行的体积相加。
然后,我们对数据框中的每一行再次迭代。第一个 if 子句丢弃值本身(如果你想在数据框中包含每个对象的体积,你可以简单地删除这个子句),elif 子句检查 x_pos 和 y_pos 是否是在 2.5 毫米的绝对距离内。
最后,我们将总体积除以项目数量(我也将结果四舍五入到小数点后两位,但如果您想要更多小数位,也可以将其删除)。这为我们提供了以下列表:
[6.33, 8.12, 8.43, 8.29, 8.4, 8.33, 8.43, 8.57, 7.75, 8.14]
因此,我们可以将计算出的列表加入到原始数据框中。
df["volume_avg"] = values
df
输出结果如下:
ID name pos_x pos_y volume volume_avg
0 1 A 1.0 1.5 10 6.33
1 2 A 3.5 3.0 6 8.12
2 3 A 4.0 4.0 8 8.43
3 4 A 4.5 4.5 9 8.29
4 5 A 5.0 6.0 10 8.40
5 1 B 1.2 1.2 4 8.33
6 3 B 4.3 4.4 8 8.43
7 4 B 4.5 4.2 7 8.57
8 2 C 3.0 3.3 9 7.75
9 3 C 4.2 4.1 10 8.14
希望对您有所帮助。我确信有更简洁的方法可以做到这一点,我也非常感谢对提议的解决方案的反馈!
我有一个数据框,它由五列“ID”、“Name”、“pos_x”、“pos_y”和“Volume”组成,如下所示:
ID | Name | pos_x | pos_y | volume
1 | A | 1 | 1.5 | 10
2 | A | 3.5 | 3 | 6
3 | A | 4 | 4 | 8
4 | A | 4.5 | 4.5 | 9
5 | A | 5 | 6 | 10
1 | B | 1.2 | 1.2 | 4
3 | B | 4.3 | 4.4 | 8
4 | B | 4.5 | 4.2 | 7
2 | C | 3 | 3.3 | 9
3 | C | 4.2 | 4.1 | 10
我现在想在数据框 ("volume_avg") 中创建一个新列,其中计算所有 ID 的体积的平均值,其半径在 2.5 毫米到各自的ID。
我的想法是先运行遍历每个名字的每个ID(因为名字+ID是主键)然后看每个ID的位置x和y。使用 if 循环,然后我将检查 ID 是否是邻居。
所以条件是:
if pos_x(当前 ID)< pos_x(所有其他 ID)- 2.5 或 > pos_x(所有其他 ID)+ 2.5
else if pos_y(当前 ID)< pos_y(所有其他 ID)- 2.5 或 > pos_y(所有其他 ID)+ 2.5
然后计算 sum(volume)/count(ID's)
否则什么都没有
不幸的是,我不知道如何在 python 代码中写下这些注意事项.... 如果你能帮助我,我会很高兴。非常感谢。
大卫
我将 if 和 else 部分中的条件解释为 (x,y)
坐标上的矩形限制。如果这不正确,请告诉我,我可以调整 if/else.
import pandas as pd
# create the structure of example dataframe
df = pd.DataFrame([[1, 'A', 1, 1.5, 10],
[2, 'A', 3.5, 3, 6],
[3, 'A', 4, 4, 8],
[4, 'A', 4.5, 4.5, 9],
[5 ,'A' , 5 , 6 , 10],
[1 ,'B' , 1.2 , 1.2 , 4],
[3 ,'B' , 4.3 , 4.4 , 8],
[4 ,'B' , 4.5 , 4.2 , 7],
[2 ,'C' , 3 , 3.3 , 9],
[3 ,'C' , 4.2 , 4.1 , 10],
],
columns=['ID', 'Name', 'pos_x', 'pos_y', 'volume'])
# create volume average with rows that meet criterion
volume_avgs = []
for g, grouper in df.groupby('Name'):
for base_row in grouper.iterrows():
v_sum = 0
v_count = 0
for row in grouper.iterrows():
if row[1].ID == base_row[1].ID: # skip the item itself
continue
elif abs(row[1].pos_x - base_row[1].pos_x) < 2.5 or abs(row[1].pos_y - base_row[1].pos_y) < 2.5:
v_sum += row[1].volume
v_count += 1
volume_avgs.append([base_row[1].ID, g, v_sum / v_count if v_count > 0 else 0, v_count])
df_vol_avgs = pd.DataFrame(volume_avgs, columns=['ID', 'Name', 'volume_avg', 'volume_count'])
merged_df = df.merge(df_vol_avgs, on=['ID', 'Name'])
merged_df
请注意,如果实际数据很大,这可能不会很好地扩展。由于双 for 循环,特别是对于具有大量数据的组。此外,如果您想要 None
或 Nan
如果附近的平均点总数为 0,您可以将 if/else 从
v_sum / v_count if v_count > 0 else 0
到
v_sum / v_count if v_count > 0 else None
对于 None
的情况和 Nan
的情况类似,比如使用 numpy.nan
。
我找到了一种可行的方法,但它不是最干净的方法,可能可以通过多种方式进行优化。
首先,我们导入 pandas 并创建数据框:
import pandas as pd
ID = [1,2,3,4,5,1,3,4,2,3]
name = ["A","A","A","A","A","B","B","B","C","C"]
pos_x = [1,3.5,4,4.5,5,1.2,4.3,4.5,3,4.2]
pos_y = [1.5,3,4,4.5,6,1.2,4.4,4.2,3.3,4.1]
volume = [10,6,8,9,10,4,8,7,9,10]
dict = {"ID": ID, "name": name, "pos_x":pos_x, "pos_y":pos_y,"volume":volume}
df = pd.DataFrame(dict)
然后,我们声明一个空列表来存储我们的结果并迭代数据框:
values = []
for i in df.itertuples():
posX = i.pos_x
posY = i.pos_y
counter = 0
volume_counter = 0
for j in df.itertuples():
if i == j:
pass
elif abs(j.pos_x - posX) <= 2.5 and abs(j.pos_y - posY) <= 2.5:
counter += 1
volume_counter += j.volume
else:
pass
values.append(round(volume_counter/counter,2))
对于数据框的每一行,我们得到 x 和 y 位置。我们也将counter和volume_counter设置为0。Counter统计有多少物品满足距离其他位置2.5mm以内的条件,volume_counter将满足条件的行的体积相加。
然后,我们对数据框中的每一行再次迭代。第一个 if 子句丢弃值本身(如果你想在数据框中包含每个对象的体积,你可以简单地删除这个子句),elif 子句检查 x_pos 和 y_pos 是否是在 2.5 毫米的绝对距离内。
最后,我们将总体积除以项目数量(我也将结果四舍五入到小数点后两位,但如果您想要更多小数位,也可以将其删除)。这为我们提供了以下列表:
[6.33, 8.12, 8.43, 8.29, 8.4, 8.33, 8.43, 8.57, 7.75, 8.14]
因此,我们可以将计算出的列表加入到原始数据框中。
df["volume_avg"] = values
df
输出结果如下:
ID name pos_x pos_y volume volume_avg
0 1 A 1.0 1.5 10 6.33
1 2 A 3.5 3.0 6 8.12
2 3 A 4.0 4.0 8 8.43
3 4 A 4.5 4.5 9 8.29
4 5 A 5.0 6.0 10 8.40
5 1 B 1.2 1.2 4 8.33
6 3 B 4.3 4.4 8 8.43
7 4 B 4.5 4.2 7 8.57
8 2 C 3.0 3.3 9 7.75
9 3 C 4.2 4.1 10 8.14
希望对您有所帮助。我确信有更简洁的方法可以做到这一点,我也非常感谢对提议的解决方案的反馈!