用两者之间的值填充pandas数据帧

时间:2015-03-01 19:31:24

标签: python pandas

我是新手使用熊猫但想要更好地学习它。我目前正面临一个问题。我有一个看起来像这样的DataFrame:

        0    1    2
0   chr2L    1    4
1   chr2L    9   12
2   chr2L   17   20
3   chr2L   23   23
4   chr2L   26   27
5   chr2L   30   40
6   chr2L   45   47
7   chr2L   52   53
8   chr2L   56   56
9   chr2L   61   62
10  chr2L   66   80

我想得到这样的东西:

            0    1    2    3
    0   chr2L    0    1    0
    1   chr2L    1    2    1
    2   chr2L    2    3    1
    3   chr2L    3    4    1
    4   chr2L    4    5    0
    5   chr2L    5    6    0
    6   chr2L    6    7    0
    7   chr2L    7    8    0
    8   chr2L    8    9    0
    9   chr2L    9   10    1
   10   chr2L   10   11    1
   11   chr2L   11   12    1
   12   chr2L   12   13    0
   And so on...

因此,用零填充缺失的区间,并将当前区间保存为1(如果有一种简单的方法可以保存"边界"位置(初始数据中区间的边界)为同时0.5也可能有帮助)将所有数据分成1个长度的间隔。

在数据中,第0列中有多个字符串值,应分别对每个字符串值进行此操作。它们需要不同长度的最终数据(应该得到0或1的最后一个值是不同的)。非常感谢您在熊猫中处理此问题的帮助。

1 个答案:

答案 0 :(得分:1)

这适用于您的第一段和大部分第二段。作为练习留下:完成插入insideness=0行(见结束):

import pandas as pd
# dummied-up version of your data, but with column headers for readability:
df = pd.DataFrame({'n':['a']*4 + ['b']*2, 'a':[1,6,8,5,1,5],'b':[4,7,10,5,3,7]})



# splitting up a range, translated into df row terms:
def onebyone(dfrow):
    a = dfrow[1].a; b = dfrow[1].b; n = dfrow[1].n
    count = b - a
if count >= 2:
    interior = [0.5]+[1]*(count-2)+[0.5]
elif count == 1:
    interior = [0.5]
elif count == 0:
    interior = []

return {'n':[n]*count, 'a':range(a, a + count),
        'b':range(a + 1, a + count + 1),
        'insideness':interior}

编辑使用pandas 0.15中的新增pd.concat()来合并中间结果:

# Into a new dataframe:
intermediate = []

for label in set(df.n):
    for row in df[df.n == label].iterrows():
        intermediate.append(pd.DataFrame(onebyone(row)))

df_onebyone = pd.concat(intermediate)
df_onebyone.index = range(len(df_onebyone))

最后是一个识别缺失行的草图,您可以编辑该行以匹配上述for循环,将行添加到最终数据帧中:

 # for times in the overall range describing 'a'
 for i in range(int(newd[newd.n=='a'].a.min()),int(newd[newd.n=='a'].a.max())): 
    # if a time isn't in an existing 0.5-1-0.5 range:
    if i not in newd[newd.n=='a'].a.values:
        # these are the values to fill in a 0-row
        print '%d, %d, 0'%(i, i+1)

或者,如果您知道将为每个a排序n列,您可以跟踪onebyone()处理的最后一个结束值,并插入一些额外的行以赶上您将要传递给onebyone()的下一个起始值。