我有這個資料框:
1 2 3
datetime
2021-01-23 00:01:00 10.0 11.0 15.0
2021-01-23 00:02:00 12.0 10.0 NaN
2021-01-23 00:03:00 16.0 12.0 NaN
(實際上,還有更多的列,例如 1-3...)
我想像這樣添加兩列:
1 2 3 new_max new_max_col
datetime
2021-01-23 00:01:00 10.0 11.0 15.0 15.0 3
2021-01-23 00:02:00 12.0 10.0 NaN NaN NaN
2021-01-23 00:03:00 16.0 12.0 NaN 16.0 1
需要采取的行動:
列
new_max:將行中的最高值復制到此列,但如果此行中有 NaN,則僅當它高于 NaN 之前的最后一個值(來自前幾行)。否則將值設定new_max為 NaN。Column
new_max_col:設定為new_max從中獲取值的列的名稱。
我的問題:如果我只是.fillna(method='ffill')在比較之前使用,我會new_max在第二行得到 15.0 ,但這是錯誤的。只應將“新”高值復制到new_max,而來自的值.fillna應僅用于比較。
創建原始資料框的代碼:
import io, pandas as pd, numpy as np
t = io.StringIO("""
datetime|1|2|3
2021-01-23 00:01:00|10|11|15
2021-01-23 00:02:00|12|10|NaN
2021-01-23 00:03:00|16|12|NaN""")
df = pd.read_csv(t, sep='|', parse_dates=['datetime'], dtype=np.float64).set_index('datetime')
!!!編輯 !!!
這里有更多不同的測驗資料來描述問題:
1 2 3
datetime
2021-01-23 00:00:00 20.0 NaN 15.0
2021-01-23 00:01:00 12.0 NaN NaN
2021-01-23 00:02:00 10.0 17.0 NaN
2021-01-23 00:03:00 NaN 14.0 18.0
2021-01-23 00:04:00 16.0 12.0 NaN
請注意,一列中可能有 2 個以上的連續 NaN(不在此示例中)。
結果應該是:
1 2 3 new_max new_max_col
datetime
2021-01-23 00:00:00 20.0 NaN 15.0 20.0 1
2021-01-23 00:01:00 12.0 NaN NaN NaN NaN
2021-01-23 00:02:00 10.0 17.0 NaN 17.0 2
2021-01-23 00:03:00 NaN 14.0 18.0 18.0 3
2021-01-23 00:04:00 16.0 12.0 NaN NaN NaN
- 第 0 行: 20 是最高的。
- 第 1 行:比較 12 和 15(15 是從“3”列的第一行開始的回顧)。15 是最高的,但它不是“新的”(它來自回顧列中 NaN 之前的最后一個數字),因此結果是 NaN。
- 第 2 行:比較 10、17、15(15 是回顧)。17是最高的。
- 第 3 行:比較 10(回顧)、14、18。18 是最高的。
- 第 4 行:比較 16、12、18(回顧)。18 是最高的,但它來自回顧,所以結果是 NaN。
生成新測驗資料框的代碼:
import io, pandas as pd, numpy as np
t = io.StringIO("""
datetime|1|2|3
2021-01-23 00:00:00| 20|NaN| 15
2021-01-23 00:01:00| 12|NaN|NaN
2021-01-23 00:02:00| 10| 17|NaN
2021-01-23 00:03:00|NaN| 14| 18
2021-01-23 00:04:00| 16| 12|NaN""")
df = pd.read_csv(t, sep='|', parse_dates=['datetime'], dtype=np.float64).set_index('datetime')
uj5u.com熱心網友回復:
如果第一行沒有缺失值,則可以Series.cummax與具有缺失值的行進行比較并設定為NaNs:
df1=df.agg(['max','idxmax'],axis=1).rename(columns={'idxmax':'max_col'}).add_prefix('new_')
mask = df1['new_max'].cummax().ne(df1['new_max']) & df.isna().any(axis=1)
df1 = df.join(df1.mask(mask))
print (df1)
1 2 3 new_max new_max_col
datetime
2021-01-23 00:01:00 10.0 11.0 15.0 15.0 3
2021-01-23 00:02:00 12.0 10.0 NaN NaN NaN
2021-01-23 00:03:00 16.0 12.0 NaN 16.0 1
編輯:
#forward fill NaNs
df11 = df.ffill()
df1 = (df11.agg(['max','idxmax'],axis=1)
.rename(columns={'idxmax':'max_col'})
.add_prefix('new_'))
#comapre only ffill values by new_max
mask = df11.where(df.isna()).max(axis=1).eq(df1['new_max'])
df1 = df.join(df1.mask(mask))
print (df1)
1 2 3 new_max new_max_col
datetime
2021-01-23 00:00:00 20.0 NaN 15.0 20.0 1
2021-01-23 00:01:00 12.0 NaN NaN NaN NaN
2021-01-23 00:02:00 10.0 17.0 NaN 17.0 2
2021-01-23 00:03:00 NaN 14.0 18.0 18.0 3
2021-01-23 00:04:00 16.0 12.0 NaN NaN NaN
EDIT1:如果還需要比較原始最大值,請添加另一個掩碼:
print (df)
1 2 3
datetime
2021-01-23 00:00:00 20.0 NaN 15.0
2021-01-23 00:01:00 12.0 NaN NaN
2021-01-23 00:02:00 10.0 17.0 NaN
2021-01-23 00:03:00 NaN 14.0 18.0
2021-01-23 00:04:00 18.0 12.0 NaN <- changed value to 18
#forward fill NaNs
df11 = df.ffill()
df1 = (df11.agg(['max','idxmax'],axis=1)
.rename(columns={'idxmax':'max_col'})
.add_prefix('new_'))
#compare only ffill values by new_max
mask = df11.where(df.isna()).max(axis=1).eq(df1['new_max'])
mask1 = df1['new_max'].ne(df.max(axis=1))
df1 = df.join(df1.mask(mask & mask1))
print (df1)
1 2 3 new_max new_max_col
datetime
2021-01-23 00:00:00 20.0 NaN 15.0 20.0 1
2021-01-23 00:01:00 12.0 NaN NaN NaN NaN
2021-01-23 00:02:00 10.0 17.0 NaN 17.0 2
2021-01-23 00:03:00 NaN 14.0 18.0 18.0 3
2021-01-23 00:04:00 18.0 12.0 NaN 18.0 1
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/376300.html
