我有以下数据框:
a1 | a2 | a3 | a4
---------------------
Bob | Cat | Dov | Edd
Cat | Dov | Bob | Edd
Edd | Cat | Dov | Bob
我希望将其转换为
Bob | Cat | Dov | Edd
---------------------
a1 | a2 | a3 | a4
a3 | a1 | a2 | a4
a4 | a2 | a3 | a1
请注意,列数等于唯一值的数量,并保留行的数量和顺序
答案 0 :(得分:9)
1) 所需方法:
更快的实现方法是对数据帧的值进行排序,并根据np.argsort
之后获得的索引对齐列。
pd.DataFrame(df.columns[np.argsort(df.values)], df.index, np.unique(df.values))
应用np.argsort
为我们提供了我们正在寻找的数据:
df.columns[np.argsort(df.values)]
Out[156]:
Index([['a1', 'a2', 'a3', 'a4'], ['a3', 'a1', 'a2', 'a4'],
['a4', 'a2', 'a3', 'a1']],
dtype='object')
2) 缓慢的广义方法:
以一些速度/效率为代价的更通用的方法是在创建数据框中存在的字符串/值及其相应列名的apply
映射之后使用dict
。
将获得的系列转换为list
表示后,请稍后使用数据框构造函数。
pd.DataFrame(df.apply(lambda s: dict(zip(pd.Series(s), pd.Series(s).index)), 1).tolist())
3) 更快的通用方法:
从df.to_dict
+ orient='records'
获取字典列表后,我们需要交换相应的键值和值对,同时循环迭代它们。
pd.DataFrame([{val:key for key, val in d.items()} for d in df.to_dict('r')])
示例测试用例:
df = df.assign(a5=['Foo', 'Bar', 'Baz'])
这两种方法都产生:
@piRSquared编辑 1
广义解决方案
def nic(df):
v = df.values
n, m = v.shape
u, inv = np.unique(v, return_inverse=1)
i = df.index.values
c = df.columns.values
r = np.empty((n, len(u)), dtype=c.dtype)
r[i.repeat(m), inv] = np.tile(c, n)
return pd.DataFrame(r, i, u)
1 我要感谢用户@ piRSquared想出一个非常快速且通用的基于numpy的替代解决方案。
答案 1 :(得分:5)
您可以使用堆栈重新整形并使用交换值和索引取消堆栈:
df_swap = (df.stack() # reshape the data frame to long format
.reset_index(level = 1) # set the index(column headers) as a new column
.set_index(0, append=True) # set the values as index
.unstack(level=1)) # reshape the data frame to wide format
df_swap.columns = df_swap.columns.get_level_values(1) # drop level 0 in the column index
df_swap
答案 2 :(得分:1)
<?= GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'idvideo',
'event_type',
'event_timestamp',
'filelocation',
//['class' => 'yii\grid\ActionColumn'],
],
]); ?>
+ numpy
pandas