Python 在pandas/numpy中将数据帧值重塑为单个基

Python 在pandas/numpy中将数据帧值重塑为单个基,python,pandas,numpy,Python,Pandas,Numpy,我有一个如下的数据帧 +----------+-------+-----+-------+-------+-----+ | Date | A | B | C | D | E | +----------+-------+-----+-------+-------+-----+ | 1-Jan-21 | 1,089 | | | 195 | | +----------+-------+-----+-------+-------+-

我有一个如下的数据帧

+----------+-------+-----+-------+-------+-----+
|   Date   |   A   |  B  |   C   |   D   |  E  |
+----------+-------+-----+-------+-------+-----+
| 1-Jan-21 | 1,089 |     |       |  195  |     |
+----------+-------+-----+-------+-------+-----+
| 2-Jan-21 |  609  | 547 |  491  | 1,091 |     |
+----------+-------+-----+-------+-------+-----+
| 3-Jan-21 | 1,440 | 824 |  184  |  512  | 665 |
+----------+-------+-----+-------+-------+-----+
| 4-Jan-21 |  704  | 632 |  345  |       | 969 |
+----------+-------+-----+-------+-------+-----+
| 5-Jan-21 |  297  |     | 1,426 |       | 555 |
+----------+-------+-----+-------+-------+-----+

df = pd.DataFrame({
    'Date' : ['1-Jan-21','2-Jan-21','3-Jan-21','4-Jan-21','5-Jan-21'],
    'A': [1089, 609, 1440, 704, 297],
    'B': [np.nan, 547, 824, 632, np.nan],
    'C': [np.nan, 491, 184, 345, 1426],
    'D': [195, 1091, 512, np.nan, np.nan],
    'E': [np.nan, np.nan, 665, 969, 555]
})
+------+-------+-----+-------+-------+-----+
| time |   A   |  B  |   C   |   D   |  E  |
+------+-------+-----+-------+-------+-----+
|  t-4 | 1,089 |     |       |       |     |
+------+-------+-----+-------+-------+-----+
|  t-3 |  609  |     |  491  |       |     |
+------+-------+-----+-------+-------+-----+
|  t-2 | 1,440 | 547 |  184  |  195  | 665 |
+------+-------+-----+-------+-------+-----+
|  t-1 |  704  | 824 |  345  | 1,091 | 969 |
+------+-------+-----+-------+-------+-----+
|   t  |  297  | 632 | 1,426 |  512  | 555 |
+------+-------+-----+-------+-------+-----+
我想忽略
Nan
值,将所有值放在一个底部/楼层,并将
Date
值重命名为
t
t-1
t-2
等等

我期望的输出如下

+----------+-------+-----+-------+-------+-----+
|   Date   |   A   |  B  |   C   |   D   |  E  |
+----------+-------+-----+-------+-------+-----+
| 1-Jan-21 | 1,089 |     |       |  195  |     |
+----------+-------+-----+-------+-------+-----+
| 2-Jan-21 |  609  | 547 |  491  | 1,091 |     |
+----------+-------+-----+-------+-------+-----+
| 3-Jan-21 | 1,440 | 824 |  184  |  512  | 665 |
+----------+-------+-----+-------+-------+-----+
| 4-Jan-21 |  704  | 632 |  345  |       | 969 |
+----------+-------+-----+-------+-------+-----+
| 5-Jan-21 |  297  |     | 1,426 |       | 555 |
+----------+-------+-----+-------+-------+-----+

df = pd.DataFrame({
    'Date' : ['1-Jan-21','2-Jan-21','3-Jan-21','4-Jan-21','5-Jan-21'],
    'A': [1089, 609, 1440, 704, 297],
    'B': [np.nan, 547, 824, 632, np.nan],
    'C': [np.nan, 491, 184, 345, 1426],
    'D': [195, 1091, 512, np.nan, np.nan],
    'E': [np.nan, np.nan, 665, 969, 555]
})
+------+-------+-----+-------+-------+-----+
| time |   A   |  B  |   C   |   D   |  E  |
+------+-------+-----+-------+-------+-----+
|  t-4 | 1,089 |     |       |       |     |
+------+-------+-----+-------+-------+-----+
|  t-3 |  609  |     |  491  |       |     |
+------+-------+-----+-------+-------+-----+
|  t-2 | 1,440 | 547 |  184  |  195  | 665 |
+------+-------+-----+-------+-------+-----+
|  t-1 |  704  | 824 |  345  | 1,091 | 969 |
+------+-------+-----+-------+-------+-----+
|   t  |  297  | 632 | 1,426 |  512  | 555 |
+------+-------+-----+-------+-------+-----+

pandas
numpy
中,我应该如何解决这个问题?

您可以使用
参数对每列的
排序
,然后通过列表理解更改
索引

df = df.set_index('Date').apply(lambda x: pd.Series(sorted(x, key=pd.notna)))
df.index = [f't-{x}' if x!=0 else 't' for x in range(len(df)-1, -1, -1)]

print (df)
        A      B       C       D      E
t-4  1089    NaN     NaN     NaN    NaN
t-3   609    NaN   491.0     NaN    NaN
t-2  1440  547.0   184.0   195.0  665.0
t-1   704  824.0   345.0  1091.0  969.0
t     297  632.0  1426.0   512.0  555.0
numpy
中,可以使用非常好的@Divakar函数:

df = df.drop('Date', axis=1)
#https://stackoverflow.com/a/44559180/2901002
df = pd.DataFrame(justify(df.to_numpy(), invalid_val=np.nan, axis=0, side='down'), 
                  columns=df.columns)

df.index = [f't-{x}' if x!=0 else 't' for x in range(len(df)-1, -1, -1)]

print (df)
          A      B       C       D      E
t-4  1089.0    NaN     NaN     NaN    NaN
t-3   609.0    NaN   491.0     NaN    NaN
t-2  1440.0  547.0   184.0   195.0  665.0
t-1   704.0  824.0   345.0  1091.0  969.0
t     297.0  632.0  1426.0   512.0  555.0
如果需要第一列
时间
使用:


您可以使用
参数按每列的
排序
,然后按列表理解更改
索引

df = df.set_index('Date').apply(lambda x: pd.Series(sorted(x, key=pd.notna)))
df.index = [f't-{x}' if x!=0 else 't' for x in range(len(df)-1, -1, -1)]

print (df)
        A      B       C       D      E
t-4  1089    NaN     NaN     NaN    NaN
t-3   609    NaN   491.0     NaN    NaN
t-2  1440  547.0   184.0   195.0  665.0
t-1   704  824.0   345.0  1091.0  969.0
t     297  632.0  1426.0   512.0  555.0
numpy
中,可以使用非常好的@Divakar函数:

df = df.drop('Date', axis=1)
#https://stackoverflow.com/a/44559180/2901002
df = pd.DataFrame(justify(df.to_numpy(), invalid_val=np.nan, axis=0, side='down'), 
                  columns=df.columns)

df.index = [f't-{x}' if x!=0 else 't' for x in range(len(df)-1, -1, -1)]

print (df)
          A      B       C       D      E
t-4  1089.0    NaN     NaN     NaN    NaN
t-3   609.0    NaN   491.0     NaN    NaN
t-2  1440.0  547.0   184.0   195.0  665.0
t-1   704.0  824.0   345.0  1091.0  969.0
t     297.0  632.0  1426.0   512.0  555.0
如果需要第一列
时间
使用:

使用简单的方法

  • 每个系列
    dropna()
  • concat开始使系列长度一致
日期 A. B C D E 0 2021-01-01 00:00:00 1089 楠 楠 楠 楠 1. 2021-01-02 00:00:00 609 楠 491 楠 楠 2. 2021-01-03 00:00:00 1440 547 184 195 665 3. 2021-01-04 00:00:00 704 824 345 1091 969 4. 2021-01-05 00:00:00 297 632 1426 512 555 使用简单的方法

  • 每个系列
    dropna()
  • concat开始使系列长度一致
日期 A. B C D E 0 2021-01-01 00:00:00 1089 楠 楠 楠 楠 1. 2021-01-02 00:00:00 609 楠 491 楠 楠 2. 2021-01-03 00:00:00 1440 547 184 195 665 3. 2021-01-04 00:00:00 704 824 345 1091 969 4. 2021-01-05 00:00:00 297 632 1426 512 555
这就像一个魅力,被接受和投票。但是,我无法理解
pandas
答案中的
sorted
方法。即使我们正在排序,最终结果也不会排序。理解正确吗?@Tommy-它应该按
参数排序,该参数正在测试不丢失的值,因此它应该工作正确,更多信息嗨,在第一行使用
pd.Series()
方法有什么好处?答案是一样的,没有它也一样。@Tommy可以随意省略它,我认为只有旧版的熊猫才有必要。这就像一种魅力,被接受并被提升。但是,我无法理解
pandas
答案中的
sorted
方法。即使我们正在排序,最终结果也不会排序。理解正确吗?@Tommy-它应该按
参数排序,该参数正在测试不丢失的值,因此它应该工作正确,更多信息嗨,在第一行使用
pd.Series()
方法有什么好处?答案是一样的,没有它也一样。@Tommy可以随意省略它,我认为只有旧版本的熊猫才有必要。