我有一個資料框,它由五列“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 的體積平均值,這些 ID 位于相應 ID 的 2.5 毫米半徑內。
我的想法是首先遍歷每個名??稱的每個 ID(因為名稱 ID 是主鍵),然后查看每個 ID 的位置 x 和 y。使用 if 回圈,我將檢查 ID 是否為鄰居。
所以條件是:
如果 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
然后計算總和(體積)/計數(ID)
否則什么都沒有
不幸的是,我不知道如何在 python 代碼中撰寫這些注意事項......如果你能幫助我,我會很高興。非常感謝。
大衛
uj5u.com熱心網友回復:
我將 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。
uj5u.com熱心網友回復:
我找到了一種有效的方法,但是,它不是最干凈的,并且可能可以通過多種方式進行優化。
首先,我們匯入 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.5 毫米以內的條件,volume_counter 將滿足條件的行的體積相加。
然后,我們對資料框中的每一行再次迭代。第一個 if 子句丟棄該值,如果它是它本身(如果你想在資料幀中包含每個物件的體積,你可以簡單地洗掉這個子句), elif 子句檢查 x_pos 和 y_pos 是否在 2.5 mm 的絕對距離內。
最后,我們附加總數量除以專案數(我還將結果四舍五入到小數點后 2 位,但如果您想要更多小數,也可以將其洗掉)。這給了我們以下串列:
[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
我希望這有幫助。我相信有更清潔的方法可以做到這一點,我也很感激對提議的解決方案的反饋!
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/424728.html
上一篇:根據條件在bash中多次列印字串
