将列移到上面并删除python数据帧中的行

将列移到上面并删除python数据帧中的行,python,python-3.x,pandas,dataframe,python-2.7,Python,Python 3.x,Pandas,Dataframe,Python 2.7,我有一个像这样的数据帧 A B C D E F G H a.1 b.1 c.1 d.1 c.2 d.2 e.1 f.1

我有一个像这样的数据帧

A        B        C        D        E        F        G        H
a.1      b.1     
                  
                  c.1      d.1 
                  c.2      d.2           e.1      f.1 
                                                      

                                                     g.1       h.1
  


创建示例数据帧

from io import StringIO

s = """A,B,C,D,E,F,G,H
a.1,b.1,,,,,,
,,c.1,d.1,,,,
,,c.2,d.2,e.1,f.1,,
,,,,,,g.1,h.1"""

df = pd.read_csv(StringIO(s))
我想删除这些额外的空格,我想让dataframe从第一行开始。有人能帮忙吗

我期望的结果是

A        B        C        D        E        F        G        H
a.1      b.1      c.1      d.1      e.1      f.1      g.1       h.1
                  c.2      d.2                                                   

您可以通过使用
第一个\u有效\u索引
找到的前面缺少的值的数量向后移动每一列:

df.apply(lambda s: s.shift(-s.first_valid_index()))
得到

     A    B    C    D    E    F    G    H
0  a.1  b.1  c.1  d.1  e.1  f.1  g.1  h.1
1  NaN  NaN  c.2  d.2  NaN  NaN  NaN  NaN
2  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN
3  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN
>>> out

     A    B    C    D    E    F    G    H
0  a.1  b.1  c.1  d.1  e.1  f.1  g.1  h.1
1            c.2  d.2
要删除充满
NaN
s的行,并用空字符串填充其余行,请执行以下操作:

out = (df.apply(lambda s: s.shift(-s.first_valid_index()))
         .dropna(how="all")
         .fillna(""))
得到

     A    B    C    D    E    F    G    H
0  a.1  b.1  c.1  d.1  e.1  f.1  g.1  h.1
1  NaN  NaN  c.2  d.2  NaN  NaN  NaN  NaN
2  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN
3  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN
>>> out

     A    B    C    D    E    F    G    H
0  a.1  b.1  c.1  d.1  e.1  f.1  g.1  h.1
1            c.2  d.2

注意:这假设您的索引是
0..N-1
;因此,如果不是,您可以事先存储它,然后恢复:

index = df.index
df = df.reset_index(drop=True)
df = (df.apply(lambda s: s.shift(-s.first_valid_index()))
        .dropna(how="all")
        .fillna(""))
df.index = index[:len(df)]

要使上拉特定于某些柱,请执行以下操作:

def pull_up(s):
    # this will be a column number; `s.name` is the column name
    col_index = df.columns.get_indexer([s.name])

   # for example: if `col_index` is either 7 or 8, pull by 4
   if col_index in (7, 8):
       return s.shift(-4)
   else:
       # otherwise, pull as much
       return s.shift(-s.first_valid_index())

# applying
df.apply(pull_up)

使用本文中的第一个解决方案-嗯,很抱歉,我没有提到这些数据是示例数据,不同列的实际数据索引是不同的。基本上,在第3,4列中,我需要向上移动1个制表符…5,6需要向上移动2个制表符…7,8需要向上移动3个制表符,第9,10列需要向上移动4个制表符tabs@sdave是的,在这种情况下,您可以将最后一个代码段与
reset_index
一起使用;你能试试吗?是的,我现在就做,我的问题是不用df(整个数据帧),我也可以简单地使用df['c']来只处理specefic列?@s当然,它应该是这样工作的。如果第一个有效索引是列0,或者我们有第一个非NaN值,它就可以完美地工作
df.iloc[:,6:8]=df.iloc[:,6:8].apply(lambda s:s.shift(-s.first\u valid\u index())
但是对于第7列和第8列,在第50行之前我有多个NaN值,但我只想向上拉4行。基本上,列应该以NaN值开始,但前4行应该删除,数据应该拉到上面。有没有办法定义什么(行-列组合)应该是第一个有效索引?