pandas - 使用 Pandas 数据框旋转和转置

标签 pandas dataframe pivot transpose

假设我有一个如下所示的 pandas 数据框:

import pandas as pd
df = pd.DataFrame({'fk ID': [1,1,2,2], 
                   'value': [3,3,4,5],
                   'valID': [1,2,1,2]})

以上将给我以下输出:

print(df)
   fk ID  value  valID
0      1      3      1
1      1      3      2
2      2      4      1
3      2      5      2

 |fk ID| value | valId |
 |  1  |  3    |   1   |
 |  1  |  3    |   2   |
 |  2  |  4    |   1   |
 |  2  |  5    |   2   |

我想以这样的方式转置和旋转它,以便获得下表和相同顺序的列名:

  fk ID  value  valID  fkID  value   valID
 |  1  |   3  |   1  |  1  |   3   |  2   | 
 |  2  |   4  |   1  |  2  |   5   |  2   |

最佳答案

我能想到的最直接的解决方案是

df = pd.DataFrame({'fk ID': [1,1,2,2], 
                   'value': [3,3,4,5],
                   'valID': [1,2,1,2]})

# concatenate the rows (Series) of each 'fk ID' group side by side 
def flatten_group(g):
    return pd.concat(row for _, row in g.iterrows())

res = df.groupby('fk ID', as_index=False).apply(flatten_group)

但是,使用 Series.iterrows 并不理想,如果每个组的规模很大,速度可能会很慢。

此外,如果“fk ID”组的大小不同,上述解决方案将不起作用。为了看到这一点,我们可以向 DataFrame 添加第三组

>>> df2 = df.append({'fk ID': 3, 'value':10, 'valID': 4}, 
                    ignore_index=True)
>>> df2

   fk ID  value  valID
0      1      3      1
1      1      3      2
2      2      4      1
3      2      5      2
4      3     10      4

>>> df2.groupby('fk ID', as_index=False).apply(flatten_group)

0  fk ID     1
   value     3
   valID     1
   fk ID     1
   value     3
   valID     2
1  fk ID     2
   value     4
   valID     1
   fk ID     2
   value     5
   valID     2
2  fk ID     3
   value    10
   valID     4
dtype: int64

结果不是预期的 DataFrame,因为 pandas 无法对齐组的列。


为了解决这个问题,我建议采用以下解决方案。它应该适用于任何大小的组,并且对于大型 DataFrame 应该更快。

import numpy as np 

def flatten_group(g):
    # flatten each group data into a single row 
    flat_data = g.to_numpy().reshape(1,-1)
    return pd.DataFrame(flat_data)

# group the rows by 'fk ID'
groups = df.groupby('fk ID', group_keys=False)

# get the maximum group size 
max_group_size = groups.size().max()

# contruct the new columns by repeating the 
# original columns 'max_group_size' times
new_cols = np.tile(df.columns, max_group_size)

# aggregate the flattened rows 
res = groups.apply(flatten_group).reset_index(drop=True) 
# update the columns 
res.columns = new_cols

输出:

# df 
>>> res

   fk ID  value  valID  fk ID  value  valID
0      1      3      1      1      3      2
1      2      4      1      2      5      2

# df2 
>>> res

   fk ID  value  valID  fk ID  value  valID
0      1      3      1    1.0    3.0    2.0
1      2      4      1    2.0    5.0    2.0
2      3     10      4    NaN    NaN    NaN

关于pandas - 使用 Pandas 数据框旋转和转置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69839539/

相关文章:

python - 如何从字符串中拆分日期和时间?

python - 在 pandas 中旋转数据

python - groupby 并根据另一列的值保留一列的信息

python - 通过复制 1 行并附加到 n 行数据帧,合并 1 行数据帧和 n 行数据帧

python - 如何用 Pandas,Python 中的几个指定单词替换一系列中的所有单词?

python - 如果字符串中的单词属于 pandas 中的单词列表,则替换该单词

使用 apply 函数族重构数据

sql-server - sql server将字符串从一列转换为三列

R:根据变量名称中的字符串将数字数据从列透视到行

mysql - 在 MySQL 中,如何获取每天每个条目的值?