私は次のようなデータフレームを持っています:
Sequence Duration1 Value1 Duration2 Value2 Duration3 Value3
1001 145 10 125 53 458 33
1002 475 20 175 54 652 45
1003 685 57 687 87 254 88
1004 125 54 175 96 786 96
1005 475 21 467 32 526 32
1006 325 68 301 54 529 41
1007 125 97 325 85 872 78
1008 129 15 429 41 981 82
1009 547 47 577 52 543 83
1010 666 65 722 63 257 87
(Duration1、Duration2、Duration3)で期間の最大値を検索し、対応する値とシーケンスを返します。
私の望ましい出力:
Sequence,Duration3,Value3
1008, 981, 82
主にNumpyに基づいて、次の非常に短いコードを試してください。
vv = df.iloc[:, 1::2].values
iRow, iCol = np.unravel_index(vv.argmax(), vv.shape)
iCol = iCol * 2 + 1
result = df.iloc[iRow, [0, iCol, iCol + 1]]
結果はSeriesです。
Sequence 1008
Duration3 981
Value3 82
Name: 7, dtype: int64
それを "再現"したい場合(最初のインデックス値、次に実際の値)、次のようなものを実行できます。
pd.DataFrame([result.values], columns=result.index)
幅の広いデータを使用すると、最初にwide_to_long
を使用して簡単に変形できます。これにより2つの列['Duration', 'Value']
が作成され、MultiIndexはそれがどの番号だったかを通知します。特定の列の順序に依存することはありません。
import pandas as pd
df = pd.wide_to_long(df, i='Sequence', j='num', stubnames=['Duration', 'Value'])
df.loc[[df.Duration.idxmax()]]
Duration Value
Sequence num
1008 3 981 82
私が質問を正しく理解した場合、次のデータフレームが与えられます:
df = pd.DataFrame(data={'Seq': [1, 2, 3], 'Dur1': [2, 7, 3],'Val1': ['x', 'y', 'z'],'Dur2': [3, 5, 1], 'Val2': ['a', 'b', 'c']})
Seq Dur1 Val1 Dur2 Val2
0 1 2 x 3 a
1 2 7 y 5 b
2 3 3 z 1 c
次の5行のコードで問題が解決します。
dur_col = [col_name for col_name in df.columns if col_name.startswith('Dur')] # ['Dur1', 'Dur2']
max_dur_name = df.loc[:, dur_col].max().idxmax()
val_name = "Val" + str([int(s) for s in max_dur_name if s.isdigit()][0])
filter_col = ['Seq', max_dur_name, val_name]
df_res = df[filter_col].sort_values(max_dur_name, ascending=False).head(1)
そしてあなたは得る:
Seq Dur1 Val1
1 2 7 y
「Dur」で始まる列を自動的に取得し、より長い期間の列名を見つけます。
dur_col = [col_name for col_name in df.columns if col_name.startswith('Dur')] # ['Dur1', 'Dur2']
max_dur_name = df.loc[:, dur_col].max().idxmax()
val_name = "Val" + str([int(s) for s in max_dur_name if s.isdigit()][0])
興味のある列を選択してください:
filter_col = ['Seq', max_dur_name, val_name]
関心のある列をフィルタリングします。max_dur_name
と検索結果が表示されます:
df_res = df[filter_col].sort_values(max_dur_name, ascending=False).head(1)
# output:
Seq Dur1 Val1
1 2 7 y
@ Massifoxの回答 と少し似ていますが、追加する価値があるほど十分に異なると思います。
mvc = df[[name for name in df.columns if 'Duration' in name]].max().idxmax()
mvidx = df[mvc].idxmax()
valuecol = 'Value' + mvc[-1]
df.loc[mvidx, ['Sequence', mvc, valuecol]]
mvc
を取得します(mvc
は'Durantion3'
例に従ってください)。mvidx
を取得します(mvidx
は7
)。valuecol
is 'Value3'
)。最後にloc
を使用して、目的の出力を選択します。
Sequence 1008
Duration3 981
Value3 82
Name: 7, dtype: int64
ここに別の方法があります、
m=df.set_index('Sequence') #set Sequence as index
n=m.filter(like='Duration') #gets all columns with the name Duration
s=n.idxmax()[n.eq(n.values.max()).any()]
#output Duration3 1008
d = dict(Zip(m.columns[::2],m.columns[1::2])) #create a mapper dict
#{'Duration1': 'Value1', 'Duration2': 'Value2', 'Duration3': 'Value3'}
final=m.loc[s.values,s.index.union(s.index.map(d))].reset_index()
Sequence Duration3 Value3
0 1008 981 82
numpy
ウィザードを使用しない場合:df
として質問で提供されたものになります_# find the max value in the Duration columns
max_value = max(df.filter(like='Dur', axis=1).max().tolist())
# get a Boolean match of the dataframe for max_value
df_max = df[df == mv]
# get the row index
max_index = df_max.dropna(how='all').index[0]
# get the column name
max_col = df_max.dropna(axis=1, how='all').columns[0]
# get column index
max_col_index = df.columns.get_loc(max_col)
# final
df.iloc[max_index, [0, max_col_index, max_col_index + 1]]
_
_Sequence 1008
Duration3 981
Value3 82
Name: 7, dtype: int64
_
max_value = max(df.filter(like='Dur', axis=1).max().tolist())
を使用して、Duration
列内の最大値を返しましたmax_col_name = df.filter(like='Dur', axis=1).max().idxmax()
の代わりに、最大値が発生する列名を返します_test = ['Duration5', 'Duration2', 'Duration3']
print(max(test))
>>> 'Duration5'
_
idmax
を使用_# column name with max duration value
max_col_name = df.filter(like='Dur', axis=1).max().idxmax()
# index of max_col_name
max_col_idx =df.columns.get_loc(max_col_name)
# row index of max value in max_col_name
max_row_idx = df[max_col_name].idxmax()
# output with .loc
df.iloc[max_row_idx, [0, max_col_idx, max_col_idx + 1 ]]
_
_Sequence 1008
Duration3 981
Value3 82
Name: 7, dtype: int64
_
以下を使用して、列の最大値のインデックスを取得できます。
>>> idx = df['Duration3'].idxmax()
>>> idx
7
そして、以下のみを使用して関連する列:
>>> df_cols = df[['Sequence', 'Duration3', 'Value3']]
>>> df_cols.loc[idx]
Sequence 1008
Duration3 981
Value3 82
Name: 7, dtype: int64
したがって、これらすべてを1つのNice関数にラップします。
def get_max(df, i):
idx = df[f'Duration{i}'].idxmax()
df_cols = df[['Sequence', f'Duration{i}', f'Value{i}']]
return df_cols.loc[idx]
そして1..3
:
>>> max_rows = [get_max(i) for i in range(1, 4)]
>>> print('\n\n'.join(map(str, max_rows)))
Sequence 1003
Duration1 685
Value1 57
Name: 2, dtype: int64
Sequence 1010
Duration2 722
Value2 63
Name: 9, dtype: int64
Sequence 1008
Duration3 981
Value3 82
Name: 7, dtype: int64
これら3つを単一の最大行に減らす場合は、次の操作を実行できます。
>>> pairs = enumerate(max_rows, 1)
>>> by_duration = lambda x: x[1][f'Duration{x[0]}']
>>> i, max_row = max(pairs, key=by_duration)
>>> max_row
Sequence 1008
Duration3 981
Value3 82
Name: 7, dtype: int64
if len(df[df[dur1]>=df[dur2].max()])==0:
if len(df[df[dur2]>=df[dur3].max()])==0:
print(df[df[dur3].idmax()][[seq,dur3,val3]])
else:
print(df[df[dur2].idmax()][[seq,dur2,val2]])
else:
if len(df[df[dur1]>=df[dur3].max()])==0:
print(df[df[dur3].idmax()][[seq,dur3,val3]])
else:
print(df[df[dur1].idmax()][[seq,dur1,val1]])