ler*_*ygr 18 python dataframe pandas
我试图在每个时间戳找到数据框中的列名,其值与同一时间戳的时间序列中的列匹配.
这是我的数据帧:
>>> df
col5 col4 col3 col2 col1
1979-01-01 00:00:00 1181.220328 912.154923 648.848635 390.986156 138.185861
1979-01-01 06:00:00 1190.724461 920.767974 657.099560 399.395338 147.761352
1979-01-01 12:00:00 1193.414510 918.121482 648.558837 384.632475 126.254342
1979-01-01 18:00:00 1171.670276 897.585930 629.201469 366.652033 109.545607
1979-01-02 00:00:00 1168.892579 900.375126 638.377583 382.584568 132.998706
>>> df.to_dict()
{'col4': {<Timestamp: 1979-01-01 06:00:00>: 920.76797370744271, <Timestamp: 1979-01-01 00:00:00>: 912.15492332839756, <Timestamp: 1979-01-01 18:00:00>: 897.58592995700656, <Timestamp: 1979-01-01 12:00:00>: 918.1214819496729}, 'col5': {<Timestamp: 1979-01-01 06:00:00>: 1190.7244605667831, <Timestamp: 1979-01-01 00:00:00>: 1181.2203275146587, <Timestamp: 1979-01-01 18:00:00>: 1171.6702763228691, <Timestamp: 1979-01-01 12:00:00>: 1193.4145103184442}, 'col2': {<Timestamp: 1979-01-01 06:00:00>: 399.39533771666561, <Timestamp: 1979-01-01 00:00:00>: 390.98615646597591, <Timestamp: 1979-01-01 18:00:00>: 366.65203285812231, <Timestamp: 1979-01-01 12:00:00>: 384.63247469269874}, 'col3': {<Timestamp: 1979-01-01 06:00:00>: 657.09956023625466, <Timestamp: 1979-01-01 00:00:00>: 648.84863460462293, <Timestamp: 1979-01-01 18:00:00>: 629.20146872682449, <Timestamp: 1979-01-01 12:00:00>: 648.55883747413225}, 'col1': {<Timestamp: 1979-01-01 06:00:00>: 147.7613518219286, <Timestamp: 1979-01-01 00:00:00>: 138.18586102094068, <Timestamp: 1979-01-01 18:00:00>: 109.54560722575859, <Timestamp: 1979-01-01 12:00:00>: 126.25434189361377}}
Run Code Online (Sandbox Code Playgroud)
并且我希望在每个时间戳匹配值的时间序列:
>>> ts
1979-01-01 00:00:00 1181.220328
1979-01-01 06:00:00 657.099560
1979-01-01 12:00:00 126.254342
1979-01-01 18:00:00 109.545607
Freq: 6H
>>> ts.to_dict()
{<Timestamp: 1979-01-01 06:00:00>: 657.09956023625466, <Timestamp: 1979-01-01 00:00:00>: 1181.2203275146587, <Timestamp: 1979-01-01 18:00:00>: 109.54560722575859, <Timestamp: 1979-01-01 12:00:00>: 126.25434189361377}
Run Code Online (Sandbox Code Playgroud)
那么结果将是:
>>> df_result
value Column
1979-01-01 00:00:00 1181.220328 col5
1979-01-01 06:00:00 657.099560 col3
1979-01-01 12:00:00 126.254342 col1
1979-01-01 18:00:00 109.545607 col1
Run Code Online (Sandbox Code Playgroud)
我希望我的问题很清楚.任何人都知道如何获得df_result?
谢谢
格雷格
Nic*_*aro 16
只是想在多列可能具有值并且您希望列表中的所有列名的情况下添加它,您可以执行以下操作(例如,对于您想要获取所有列名的情况,值为 = 'x '):
df.apply(lambda row: row[row == 'x'].index, axis=1)
Run Code Online (Sandbox Code Playgroud)
这个想法是你将每一行变成一个系列(通过添加轴=1),其中列名现在变成了系列的索引。然后你用一个条件过滤你的系列(例如 row == 'x'),然后取索引值(又名列名!)。
And*_*den 12
这是一种,也许是不优雅的方式:
df_result = pd.DataFrame(ts, columns=['value'])
Run Code Online (Sandbox Code Playgroud)
设置一个函数来获取包含值(from ts)的列名:
def get_col_name(row):
b = (df.ix[row.name] == row['value'])
return b.index[b.argmax()]
Run Code Online (Sandbox Code Playgroud)
对于每一行,测试哪些元素等于值,并提取True的列名.
而且apply它(按行):
In [3]: df_result.apply(get_col_name, axis=1)
Out[3]:
1979-01-01 00:00:00 col5
1979-01-01 06:00:00 col3
1979-01-01 12:00:00 col1
1979-01-01 18:00:00 col1
Run Code Online (Sandbox Code Playgroud)
即使用 df_result['Column'] = df_result.apply(get_col_name, axis=1).
.
注意:有相当多的事情发生,get_col_name所以它可能需要进一步解释:
In [4]: row = df_result.irow(0) # an example row to pass to get_col_name
In [5]: row
Out[5]:
value 1181.220328
Name: 1979-01-01 00:00:00
In [6]: row.name # use to get rows of df
Out[6]: <Timestamp: 1979-01-01 00:00:00>
In [7]: df.ix[row.name]
Out[7]:
col5 1181.220328
col4 912.154923
col3 648.848635
col2 390.986156
col1 138.185861
Name: 1979-01-01 00:00:00
In [8]: b = (df.ix[row.name] == row['value'])
#checks whether each elements equal row['value'] = 1181.220328
In [9]: b
Out[9]:
col5 True
col4 False
col3 False
col2 False
col1 False
Name: 1979-01-01 00:00:00
In [10]: b.argmax() # index of a True value
Out[10]: 0
In [11]: b.index[b.argmax()] # the index value (column name)
Out[11]: 'col5'
Run Code Online (Sandbox Code Playgroud)
可能有更有效的方法来做到这一点......
tdy*_*tdy 12
df.eq()约 300 倍的加速df.apply()其他答案很好,但与矢量化相比非常慢df.eq():
df.loc[ts.index].eq(ts, axis=0).idxmax(axis=1)
# 1979-01-01 00:00:00 col5
# 1979-01-01 06:00:00 col3
# 1979-01-01 12:00:00 col1
# 1979-01-01 18:00:00 col1
# dtype: object
Run Code Online (Sandbox Code Playgroud)
loc[ts.index]返回与时间戳df匹配的行tseq(ts, axis=0)将每个值与 ( ) 的ts一行进行比较axis=0df
eq(ts[:, None])将是numpy 广播等效项idxmax(axis=1)axis=1返回每行中的第一个匹配列 ( )测试数据:
index = pd.date_range('2000-01-01', periods=n, freq='1T')
df = pd.DataFrame(np.random.random(size=(n, 5)), index=index).add_prefix('col')
ts = df.apply(np.random.choice, axis=1).sample(frac=0.9)
np.isclose()更安全的浮动比较除非您有特定原因要测试严格相等,否则应将 float 与宽容进行比较,例如,使用isclose():
用于与isclose()进行比较,其中拉伸到与 相同的大小:dfts[:, None] tsdf
close = np.isclose(df.loc[ts.index], ts[:, None])
# array([[ True, False, False, False, False],
# [False, False, True, False, False],
# [False, False, False, False, True],
# [False, False, False, False, True]])
Run Code Online (Sandbox Code Playgroud)
然后,像以前一样,使用idxmax(axis=1)提取每行的第一个匹配列:
pd.DataFrame(close, index=ts.index, columns=df.columns).idxmax(axis=1)
# 1979-01-01 00:00:00 col5
# 1979-01-01 06:00:00 col3
# 1979-01-01 12:00:00 col1
# 1979-01-01 18:00:00 col1
# dtype: object
Run Code Online (Sandbox Code Playgroud)
使用将与(并且因此比isclose())一样快:eq()df.apply()
请注意,如果您有更复杂的连接条件,请使用df.merge()、df.join()或df.reindex()。对于OP的问题,这些都太过分了,但看起来像这样:
df.merge(ts.rename('ts'), left_index=True, right_index=True)df.join(ts.rename('ts'), how='right')df.reindex(ts.index)根据Andy的详细解答,选择每行最高值列名的解决方案可以简化为一行:
df['column'] = df.apply(lambda x: df.columns[x.argmax()], axis = 1)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
30127 次 |
| 最近记录: |