Python 3.x 将列标题转换为新列并保留每列的值

Python 3.x 将列标题转换为新列并保留每列的值,python-3.x,pandas,Python 3.x,Pandas,UPD:在页面底部粘贴了一个数据框作为示例 我的原始xls文件如下所示: 我需要两个动作才能让它看起来像下面这样: 首先,我需要用上面单元格中显示的值填充空行值。这已通过以下功能实现: def get_csv(): #Read csv file df = pd.read_excel('test.xls') df = df.fillna(method='ffill') return df 其次,我使用了stack和set\u index: df = (df.s

UPD:在页面底部粘贴了一个数据框作为示例

我的原始xls文件如下所示:

我需要两个动作才能让它看起来像下面这样:

首先,我需要用上面单元格中显示的值填充空行值。这已通过以下功能实现:

def get_csv():
    #Read csv file
    df = pd.read_excel('test.xls')
    df = df.fillna(method='ffill')
    return df
其次,我使用了
stack
set\u index

df = (df.set_index(['Country', 'Gender', 'Arr-Dep'])
         .stack()
         .reset_index(name='Value')
         .rename(columns={'level_3':'Year'}))
我想知道是否有更简单的方法。是否有将数据框、excel等转换为所需格式的库

excel导入后的原始数据框:

Country  Gender                          Direction   1974   1975   1976  
0   Austria    Male  IN  13728   8754   9695   
1       NaN     NaN  OUT  17977  12271   9899   
2       NaN  Female  IN   8541   6465   6447   
3       NaN     NaN  OUT   8450   7190   6288   
4       NaN   Total  IN  22269  15219  16142   
5       NaN     NaN  OUT  26427  19461  16187   
6   Belgium    Male  IN   2412   2245   2296   
7       NaN     NaN  OUT   2800   2490   2413   
8       NaN  Female  IN   2105   2022   2057   
9       NaN     NaN  OUT   2100   2113   2004   
10      NaN   Total  IN   4517   4267   4353   
11      NaN     NaN  OUT   4900   4603   4417

使用替代解决方案,但如果需要相同的列顺序,如
堆叠
数据帧
,则需要添加:





使用替代解决方案,但如果需要相同的列顺序,如
堆叠
数据帧
,则需要添加:




堆栈
我喜欢你的方法。我会用几种方法来改变它

  • 使用向前填充的特定方法
    ffill
  • 在堆叠之前重命名柱轴,以避免以后重命名柱(个人偏好)


  • 努比 我想制定一个定制方法。这应该很快

    def cstm_ffill(s):
      i = np.flatnonzero(s.notna())
      i = np.concatenate([[0], i, [len(s)]])
      d = np.diff(i)
      a = s.values[i[:-1].repeat(d)]
      return a
    
    def cstm_melt(df):
      c = cstm_ffill(df.Country)
      g = cstm_ffill(df.Gender)
      d = cstm_ffill(df.Direction)
      y = df.columns[3:].values
    
      k = len(y)
    
      i = np.column_stack([c, g, d])
      v = np.column_stack([*map(df.get, y)]).ravel()
    
      df_ = pd.DataFrame(
          np.column_stack([i.repeat(k, axis=0), v, np.tile(y, len(i))]),
          columns=['Country', 'Gender', 'Direction', 'Year', 'Value']
      )
      return df_
    
    cstm_melt(df)
    
        Country  Gender Direction   Year Value
    0   Austria    Male        IN  13728  1974
    1   Austria    Male        IN   8754  1975
    2   Austria    Male        IN   9695  1976
    3   Austria    Male       OUT  17977  1974
    4   Austria    Male       OUT  12271  1975
    5   Austria    Male       OUT   9899  1976
    ...
    
    堆栈
    我喜欢你的方法。我会用几种方法来改变它

  • 使用向前填充的特定方法
    ffill
  • 在堆叠之前重命名柱轴,以避免以后重命名柱(个人偏好)


  • 努比 我想制定一个定制方法。这应该很快

    def cstm_ffill(s):
      i = np.flatnonzero(s.notna())
      i = np.concatenate([[0], i, [len(s)]])
      d = np.diff(i)
      a = s.values[i[:-1].repeat(d)]
      return a
    
    def cstm_melt(df):
      c = cstm_ffill(df.Country)
      g = cstm_ffill(df.Gender)
      d = cstm_ffill(df.Direction)
      y = df.columns[3:].values
    
      k = len(y)
    
      i = np.column_stack([c, g, d])
      v = np.column_stack([*map(df.get, y)]).ravel()
    
      df_ = pd.DataFrame(
          np.column_stack([i.repeat(k, axis=0), v, np.tile(y, len(i))]),
          columns=['Country', 'Gender', 'Direction', 'Year', 'Value']
      )
      return df_
    
    cstm_melt(df)
    
        Country  Gender Direction   Year Value
    0   Austria    Male        IN  13728  1974
    1   Austria    Male        IN   8754  1975
    2   Austria    Male        IN   9695  1976
    3   Austria    Male       OUT  17977  1974
    4   Austria    Male       OUT  12271  1975
    5   Austria    Male       OUT   9899  1976
    ...
    

    请提供一份报告。在这里,这意味着以文本形式提供数据,而不是图像/链接。另请参见。@jpp在本例中,我不需要发布数据帧。我可以更新这个问题,关键是我们很多人喜欢测试我们的解决方案。不幸的是,我们中的许多人也懒得做最耗时的工作,即从头开始构建数据帧。@jpp是正确的。然而,我不会把它描述为懒惰,而是希望尊重我们的时间。给我们提供他们正在处理的数据所需的时间远远少于我们制作数据所需的时间。此外,OP提供的数据是数据。我们制作的数据可能代表OP使用的内容。如果我们的猜测是错误的,那么这就更浪费时间了。我找不到粘贴数据帧的最佳方法。我已经对它进行了简化,但我认为我应该将其发布为JSON格式。我想链接到这个文件会更好。把你的想法告诉我。请提供一个答案。在这里,这意味着以文本形式提供数据,而不是图像/链接。另请参见。@jpp在本例中,我不需要发布数据帧。我可以更新这个问题,关键是我们很多人喜欢测试我们的解决方案。不幸的是,我们中的许多人也懒得做最耗时的工作,即从头开始构建数据帧。@jpp是正确的。然而,我不会把它描述为懒惰,而是希望尊重我们的时间。给我们提供他们正在处理的数据所需的时间远远少于我们制作数据所需的时间。此外,OP提供的数据是数据。我们制作的数据可能代表OP使用的内容。如果我们的猜测是错误的,那么这就更浪费时间了。我找不到粘贴数据帧的最佳方法。我已经对它进行了简化,但我认为我应该将其发布为JSON格式。我想链接到这个文件会更好。告诉我你的想法。是的,我发现只有这一种方法明显比
    melt
    慢,但不是很好的样本,所以不是100%确定。@ApoloRadomer。如果您关心性能,请参阅我的更新。很高兴你有了答案。是的,只有这一个方法显然比我发现的
    melt
    慢,但不是很好的样本,所以不是100%确定。@ApoloRadomer。如果您关心性能,请参阅我的更新。很高兴你有你的答案。
    df1 = (df.ffill()
             .melt(id_vars=['Country','Gender','Direction'],var_name="Date", value_name='Value')
             .sort_values(['Country', 'Gender','Direction'])
             .reset_index(drop=True))
    
    print (df1)
        Country  Gender Direction  Date  Value
    0   Austria  Female        IN  1974   8541
    1   Austria  Female        IN  1975   6465
    2   Austria  Female        IN  1976   6447
    3   Austria  Female       OUT  1974   8450
    4   Austria  Female       OUT  1975   7190
    5   Austria  Female       OUT  1976   6288
    6   Austria    Male        IN  1974  13728
    7   Austria    Male        IN  1975   8754
    8   Austria    Male        IN  1976   9695
    9   Austria    Male       OUT  1974  17977
    10  Austria    Male       OUT  1975  12271
    11  Austria    Male       OUT  1976   9899
    12  Austria   Total        IN  1974  22269
    13  Austria   Total        IN  1975  15219
    14  Austria   Total        IN  1976  16142
    15  Austria   Total       OUT  1974  26427
    16  Austria   Total       OUT  1975  19461
    17  Austria   Total       OUT  1976  16187
    18  Belgium  Female        IN  1974   2105
    19  Belgium  Female        IN  1975   2022
    20  Belgium  Female        IN  1976   2057
    21  Belgium  Female       OUT  1974   2100
    22  Belgium  Female       OUT  1975   2113
    23  Belgium  Female       OUT  1976   2004
    24  Belgium    Male        IN  1974   2412
    25  Belgium    Male        IN  1975   2245
    26  Belgium    Male        IN  1976   2296
    27  Belgium    Male       OUT  1974   2800
    28  Belgium    Male       OUT  1975   2490
    29  Belgium    Male       OUT  1976   2413
    30  Belgium   Total        IN  1974   4517
    ...
    ...
    
    df.ffill().set_index(
        ['Country', 'Gender', 'Direction']
    ).rename_axis('Year', 1).stack().reset_index(name='Value')
    
        Country  Gender Direction  Year  Value
    0   Austria    Male        IN  1974  13728
    1   Austria    Male        IN  1975   8754
    2   Austria    Male        IN  1976   9695
    3   Austria    Male       OUT  1974  17977
    4   Austria    Male       OUT  1975  12271
    5   Austria    Male       OUT  1976   9899
    ...
    
    def cstm_ffill(s):
      i = np.flatnonzero(s.notna())
      i = np.concatenate([[0], i, [len(s)]])
      d = np.diff(i)
      a = s.values[i[:-1].repeat(d)]
      return a
    
    def cstm_melt(df):
      c = cstm_ffill(df.Country)
      g = cstm_ffill(df.Gender)
      d = cstm_ffill(df.Direction)
      y = df.columns[3:].values
    
      k = len(y)
    
      i = np.column_stack([c, g, d])
      v = np.column_stack([*map(df.get, y)]).ravel()
    
      df_ = pd.DataFrame(
          np.column_stack([i.repeat(k, axis=0), v, np.tile(y, len(i))]),
          columns=['Country', 'Gender', 'Direction', 'Year', 'Value']
      )
      return df_
    
    cstm_melt(df)
    
        Country  Gender Direction   Year Value
    0   Austria    Male        IN  13728  1974
    1   Austria    Male        IN   8754  1975
    2   Austria    Male        IN   9695  1976
    3   Austria    Male       OUT  17977  1974
    4   Austria    Male       OUT  12271  1975
    5   Austria    Male       OUT   9899  1976
    ...