我正在嘗試找出一種方法,將 nan 放在每行的另一列中的 2 個開始/結束值之間不存在的列中。假設我有以下資料框:
df = pd.DataFrame({'39' : [1, np.nan, 3],
'40' : [2, 4, 5],
'41' : [3, 1, 4],
'42' : [2, 5, 2],
'43' : [1, 1, np.nan],
'start' : [39, 40, 41],
'end' : [41, 41, 43]})
39 40 41 42 43 start end
0 1.0 2 3 2 1 39 41
1 NaN 4 1 5 1 40 41
2 3.0 5 4 2 3 41 43
我想在不在開始/結束列號(包括)之間的編號列中放置一個 nan,以獲得以下內容:
39 40 41 42 43 start end
0 1.0 2.0 3 NaN NaN 39 41
1 NaN 4.0 1 NaN NaN 40 41
2 NaN NaN 4 2.0 3.0 41 43
我目前能想到的唯一方法是遍歷行或列以檢查是否在開始和結束之間,但我知道遍歷資料幀是不好的做法。我可以將列轉換為串列并遍歷它們并重新分配,但我只是想知道是否有更有效的方法來實作這一目標?
編輯:我應該注意到數字列是周數,所以它們有可能超過一年(例如 51、52、1、2、3,然后開始可能是 51,結束可能是 1)。我想知道在執行此操作之前是否需要列出要保留的列號,因為在這種情況下使用 < 或 > 不起作用。
一個例子:
df2 = pd.DataFrame({'51' : [1, np.nan, 3],
'52' : [2, 4, 5],
'1' : [3, 1, 4],
'2' : [2, 5, 2],
'3' : [1, 1, 3],
'start' : [51, 52, 52],
'end' : [1, 2, 1]})
51 52 1 2 3 start end
0 1.0 2 3 2 1 51 1
1 NaN 4 1 5 1 52 2
2 3.0 5 4 2 3 52 1
輸出:
51 52 1 2 3 start end
0 1.0 2 3 NaN NaN 51 1
1 NaN 4 1 5.0 NaN 52 2
2 NaN 5 4 NaN NaN 52 1
uj5u.com熱心網友回復:
我們可以在這里使用stack和unstack:
df = df.set_index(["start", "end"]).stack()
idx = df.index
values = idx.get_level_values(2).astype(int)
start = idx.get_level_values(0)
end = idx.get_level_values(1)
df.where((values >= start) & (values <= end)).unstack().reset_index()
start end 39 40 41 42 43
0 39 41 1.0 2.0 3.0 NaN NaN
1 40 41 NaN 4.0 1.0 NaN NaN
2 41 43 NaN NaN 4.0 2.0 NaN
uj5u.com熱心網友回復:
Numpy 解決方案在開始和結束之間進行比較:
df.columns = df.columns[:-2].astype(int).tolist() df.columns[-2:].tolist()
s = df['start'].to_numpy()
e = df['end'].to_numpy()
cols = df.columns[:-2].to_numpy()
m = (s[:, None] <= cols) & (e[:, None] >= cols)
df.iloc[:, :-2] = df.iloc[:, :-2].where(m)
print (df)
39 40 41 42 43 start end
0 1.0 2.0 3 NaN NaN 39 41
1 NaN 4.0 1 NaN NaN 40 41
2 NaN NaN 4 2.0 NaN 41 43
編輯:如果不可能按值與累積總和進行比較,e從后面測驗是否1在兩個掩碼中:
s = df['start'].astype(str).to_numpy()
e = df['end'].astype(str).to_numpy()
cols = df.columns[:-2].to_numpy()
m1 = np.cumsum((s[:, None] == cols), axis=1) == 1
m2 = np.cumsum((e[:, None] == cols[::-1]), axis=1)[:, ::-1] == 1
m = m1 & m2
df.iloc[:, :-2] = df.iloc[:, :-2].where(m)
print (df)
51 52 1 2 3 start end
0 1.0 2 3 NaN NaN 51 1
1 NaN 4 1 5.0 NaN 52 2
2 NaN 5 4 NaN NaN 52 1
uj5u.com熱心網友回復:
for column in ['39', '40', '41', '42', '43']:
df[column].loc[(float(column) < df['start']) | (float(column) > df['end'])] = np.NaN
將列印:
39 40 41 42 43 start end
0 1.0 2.0 3.0 NaN NaN 39 41
1 NaN 4.0 1.0 NaN NaN 40 41
2 NaN NaN 4.0 2.0 NaN 41 43
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/366376.html
下一篇:在Pandas中創建和洗掉列
