根据条件熔化 pandas 数据框
Melt pandas dataframe based on condition
我有一个具有以下格式的数据框
timestamp
ID
Col1
Col2
Col3
Col4
UsefulCol
16/11/2021
1
0.2
0.1
Col3
17/11/2021
1
0.3
0.8
Col3
17/11/2021
2
10
Col2
17/11/2021
3
0.1
2
Col4
我想把它“融化”成这种格式:
timestamp
ID
Col
Value
16/11/2021
1
Col3
0.1
17/11/2021
1
Col3
0.8
17/11/2021
2
Col2
10
17/11/2021
3
Col4
2
我该怎么做?
作为数据框输入:
from numpy import nan
df = pd.DataFrame({'timestamp': ['16/11/2021', '17/11/2021', '17/11/2021', '17/11/2021'],
'ID': [1, 1, 2, 3],
'Col1': [0.2, 0.3, nan, nan],
'Col2': [nan, nan, 10.0, nan],
'Col3': [0.1, 0.8, nan, 0.1],
'Col4': [nan, nan, nan, 2.0],
'UsefulCol': ['Col3', 'Col3', 'Col2', 'Col4']})
首先尝试用有用的值创建一个列:
df['Value'] = df.apply(lambda x: x[x.UsefulCol], axis=1)
timestamp ID Col1 Col2 Col3 Col4 UsefulCol Value
16/11/2021 1 0.2 0.1 Col3 0.1
17/11/2021 1 0.3 0.8 Col3 0.8
17/11/2021 2 10 Col2 10
17/11/2021 3 0.1 2 Col4 2
然后,您可以删除要熔化的列:
df.drop(['Col1', 'Col2', 'Col3', 'Col4], axis=1, inplace=True)
timestamp ID UsefulCol Value
16/11/2021 1 Col3 0.1
17/11/2021 1 Col3 0.8
17/11/2021 2 Col2 10
17/11/2021 3 Col4 2
如果需要,重命名您的列:
df.rename({'UsefulCol':'Col'}, axis=1, inplace=True)
或
df.columns = [timestamp', 'ID', 'Col', 'Value]
这是一个使用一点 numpy 的矢量解决方案:
import numpy as np
# select columns to pseudo-melt (this could be a manual list cols=['A', 'B', 'C'])
cols = df.filter(regex='^Col').columns
# slice the needed values (they will be on the diagonal) and keep only diagonal
df['Value'] = np.diag(df.filter(regex='^Col').loc[:, df['UsefulCol']].values)
# drop old columns
new_df = df.drop(columns=cols)
输出:
timestamp ID UsefulCol Value
0 16/11/2021 1 Col3 0.1000
1 17/11/2021 1 Col3 0.8000
2 17/11/2021 2 Col2 10.0000
3 17/11/2021 3 Col4 2.0000
我有一个具有以下格式的数据框
timestamp | ID | Col1 | Col2 | Col3 | Col4 | UsefulCol |
---|---|---|---|---|---|---|
16/11/2021 | 1 | 0.2 | 0.1 | Col3 | ||
17/11/2021 | 1 | 0.3 | 0.8 | Col3 | ||
17/11/2021 | 2 | 10 | Col2 | |||
17/11/2021 | 3 | 0.1 | 2 | Col4 |
我想把它“融化”成这种格式:
timestamp | ID | Col | Value |
---|---|---|---|
16/11/2021 | 1 | Col3 | 0.1 |
17/11/2021 | 1 | Col3 | 0.8 |
17/11/2021 | 2 | Col2 | 10 |
17/11/2021 | 3 | Col4 | 2 |
我该怎么做?
作为数据框输入:
from numpy import nan
df = pd.DataFrame({'timestamp': ['16/11/2021', '17/11/2021', '17/11/2021', '17/11/2021'],
'ID': [1, 1, 2, 3],
'Col1': [0.2, 0.3, nan, nan],
'Col2': [nan, nan, 10.0, nan],
'Col3': [0.1, 0.8, nan, 0.1],
'Col4': [nan, nan, nan, 2.0],
'UsefulCol': ['Col3', 'Col3', 'Col2', 'Col4']})
首先尝试用有用的值创建一个列:
df['Value'] = df.apply(lambda x: x[x.UsefulCol], axis=1)
timestamp ID Col1 Col2 Col3 Col4 UsefulCol Value
16/11/2021 1 0.2 0.1 Col3 0.1
17/11/2021 1 0.3 0.8 Col3 0.8
17/11/2021 2 10 Col2 10
17/11/2021 3 0.1 2 Col4 2
然后,您可以删除要熔化的列:
df.drop(['Col1', 'Col2', 'Col3', 'Col4], axis=1, inplace=True)
timestamp ID UsefulCol Value
16/11/2021 1 Col3 0.1
17/11/2021 1 Col3 0.8
17/11/2021 2 Col2 10
17/11/2021 3 Col4 2
如果需要,重命名您的列:
df.rename({'UsefulCol':'Col'}, axis=1, inplace=True)
或
df.columns = [timestamp', 'ID', 'Col', 'Value]
这是一个使用一点 numpy 的矢量解决方案:
import numpy as np
# select columns to pseudo-melt (this could be a manual list cols=['A', 'B', 'C'])
cols = df.filter(regex='^Col').columns
# slice the needed values (they will be on the diagonal) and keep only diagonal
df['Value'] = np.diag(df.filter(regex='^Col').loc[:, df['UsefulCol']].values)
# drop old columns
new_df = df.drop(columns=cols)
输出:
timestamp ID UsefulCol Value
0 16/11/2021 1 Col3 0.1000
1 17/11/2021 1 Col3 0.8000
2 17/11/2021 2 Col2 10.0000
3 17/11/2021 3 Col4 2.0000