如何使用Python基于动态条件分隔数据帧行

时间:2017-02-10 20:35:15

标签: python pandas numpy dataframe

奇怪的问题我似乎无法解决这个问题,我知道有一个更好的方式来看待它,我只是卡住了。我需要根据类型获取这些数据的块。 1到4在一个集合中聚集在一起,所以我想要例如,行0到8,然后是9。每个集合将作为数据库中的条目输入。

     num          date   type      signed
0   294981  2015-05-01      1        None
1   299888  2015-05-22      2  2015-05-28
2   299891  2015-05-22      2  2015-05-28
3   316150  2015-07-14      3  2015-07-23
4   336930  2015-10-13      3  2015-10-16
5   357536  2015-12-29      3  2015-12-29
6   379224  2016-03-14      3  2016-03-18
7   403862  2016-06-10      3  2016-06-10
8   414282  2016-07-26      4  2016-08-03
9   439184  2016-11-10      1  2016-11-14
10  448972  2016-12-12      2  2016-12-14
11  464306  2017-02-02      3  2017-02-06

事情是这个数据不是静态的,有些集合可能有10行类型3,没有1或4。如果我有以下内容:

     num          date   type      signed
0   294981  2015-05-01      2        None
1   299888  2015-05-22      2  2015-05-28
2   299891  2015-05-22      2  2015-05-28
3   316150  2015-07-14      3  2015-07-23
4   336930  2015-10-13      3  2015-10-16
5   357536  2015-12-29      3  2015-12-29
6   379224  2016-03-14      1  2016-03-18
7   403862  2016-06-10      3  2016-06-10
8   414282  2016-07-26      3  2016-08-03
9   439184  2016-11-10      4  2016-11-14
10  448972  2016-12-12      1  2016-12-14
11  464306  2017-02-02      2  2017-02-06

我需要离开:

     num          date   type      signed
0   294981  2015-05-01      2        None
1   299888  2015-05-22      2  2015-05-28
2   299891  2015-05-22      2  2015-05-28
3   316150  2015-07-14      3  2015-07-23
4   336930  2015-10-13      3  2015-10-16
5   357536  2015-12-29      3  2015-12-29

     num          date   type      signed
6   379224  2016-03-14      1  2016-03-18
7   403862  2016-06-10      3  2016-06-10
8   414282  2016-07-26      3  2016-08-03
9   439184  2016-11-10      4  2016-11-14

     num          date   type      signed
10  448972  2016-12-12      1  2016-12-14
11  464306  2017-02-02      2  2017-02-06

不幸的是,除了那个愚蠢的类型值之外,没有其他方法可以对这些数据进行分组。我对Pandas很有能力并且无法找到方法去做,也没有其他任何可以用来做这件事而不告诉Python 确切地要抓取哪些值,当然我不喜欢不知道数据就知道了。

非常感谢帮助! (顺便说一句,我在标题中说'动态条件',因为类型列值不是1-4,或2-4或1-3或我可以设置的任何东西。它会根据当时生成的数据而变化)

4 个答案:

答案 0 :(得分:2)

我假设您能够将这些设置分开,因为下一个的类型将比前一个更小。

您可以添加一个额外的临时列,用于添加分隔数据帧的序列号。像这样:

def separate_df(t):
   res = pd.Series()
   previous_df_no = 0
   for (index, value) in t.iteritems():
       if index==0:
           res.set_value(index,0)
       else:
           if value<t.loc[index-1]:
               previous_df_no += 1
           res.set_value(index,previous_df_no)
   return res
df['temp'] = separate_df(df.type)

然后你可以使用序列号告诉每一行属于哪个数据帧,并在分离后删除临时行。

答案 1 :(得分:2)

假设您希望在类型低于上一行中的类型后启动组,则此代码应该有效:

class Group():
    start = 0
    last_type = 0
    def four_group(self,x):
        if x < Group.last_type:
            Group.start +=1
        groupNum = Group.start
        Group.last_type = x
        return groupNum


df =  pd.read_csv("chart.csv")
zzz = Group()
df['TempGroup'] = df.type.apply(lambda x:zzz.four_group(x))

使用您的第二个数据框:

     num          date   type      signed
0   294981  2015-05-01      2        None
1   299888  2015-05-22      2  2015-05-28
2   299891  2015-05-22      2  2015-05-28
3   316150  2015-07-14      3  2015-07-23
4   336930  2015-10-13      3  2015-10-16
5   357536  2015-12-29      3  2015-12-29
6   379224  2016-03-14      1  2016-03-18
7   403862  2016-06-10      3  2016-06-10
8   414282  2016-07-26      3  2016-08-03
9   439184  2016-11-10      4  2016-11-14
10  448972  2016-12-12      1  2016-12-14
11  464306  2017-02-02      2  2017-02-06

代码返回:

       num        date  type      signed  TempGroup
0   294981    5/1/2015     2        None          0
1   299888   5/22/2015     2   5/28/2015          0
2   299891   5/22/2015     2   5/28/2015          0
3   316150   7/14/2015     3   7/23/2015          0
4   336930  10/13/2015     3  10/16/2015          0
5   357536  12/29/2015     3  12/29/2015          0
6   379224   3/14/2016     1   3/18/2016          1
7   403862   6/10/2016     3   6/10/2016          1
8   414282   7/26/2016     3    8/3/2016          1
9   439184  11/10/2016     4  11/14/2016          1
10  448972  12/12/2016     1  12/14/2016          2
11  464306    2/2/2017     2    2/6/2017          2

然后,您可以根据TempGroup拆分数据框,然后删除TempGroup列。

编辑:混合数据帧

答案 2 :(得分:0)

作为观察,我看到你的“类型”看起来像是按年分组。如果是这样,这样的事情可能适合你: getYear = lambda x: x.year data.year = data.date.apply(getYear) myGroup = data.groupby(year)

答案 3 :(得分:0)

我有类似的问题,但条件不同。可能对其他人有用。我想在我的&#34; tvshow&#34;的条件下分开行。列是21号。因此,每次在列中找到21时,我都会重置df [&#39; TempGroup&#39;]计数。 数据集摘要:

tvshow,time,duration
15,9.4,7.1
0,10.1,0.6
3,10.7,0.5

代码:

class Group():
    start = 0
    last_type = 0
    Group.start = 0
    def four_group(self,x):
        if x == 21:
            Group.start = 0
        else: Group.start += 1
        groupNum = Group.start
        Group.last_type = x
        return groupNum
# Read from .csv
df = pd.read_csv('/home/dataset.csv')
grp = Group()
df['TempGroup'] = df.tvshow.apply(lambda x:grp.four_group(x))