提取熊猫数据框的子部分

时间:2018-11-21 08:55:35

标签: python pandas dataframe

我有一个这样的数据框:

Name   ID   Level
Name1   A     1
Name2   B     2
Name3   C     3
Name4   D     1
Name5   E     2
Name6   F     1

等...

我正在寻找一种基于名称标准仅提取此数据框的一部分的方法。因此,我想从Name4开始提取所有内容,直到该组中最后一个人的名字是另一个Level1。即从Name4提取到Name5,因为Name6是Level 1。

或者再举一个例子,我想从Name1提取到Name3,因为Name4是Level 1。

我可以使用宏在Excel中执行此操作...查找Name1,查看“级别”列,如果它不是1,则获取这一行数据并继续操作,直到您击中“名称”为止再次具有1级,然后停止,然后输出此部分

希望这很有道理。

5 个答案:

答案 0 :(得分:1)

您可以执行以下操作:

创建一个包含组值的新列“ Group”,然后您可以groupby此列

g = 0
for i in df.index:
    if df.loc[i, "Level"] == 1:
        g += 1
    df.loc[i, "Group"] = g

答案 1 :(得分:1)

使用此数据框:

In [0]: df
Out[0]: 
    Name ID  Level
0  Name1  A      1
1  Name2  B      2
2  Name3  C      3
3  Name4  D      1
4  Name5  E      2
5  Name6  F      1

使用帮助列/系列来指示行是否处于特定级别(目标级别)。 target_lvl = 1

helper_series = (df['Level'] == target_lvl)

In [1]: helper_series
Out[1]: 
0     True
1    False
2    False
3     True
4    False
5     True

现在,您可以获取一个范围列表,该范围映射每个子集的开始和结束:

ranges = df.index.where(helper_series).dropna().astype(int).tolist()

In [2]: ranges
Out[2]:
[0, 3, 5]

请注意,ranges的值是属于target-lvl的每一行的索引。

最后,您只需要从ranges中提取子集:

subsets = list()
for i in range(len(ranges)):
    if i == 0:
        continue
    subsets.append(df.iloc[ ranges[i-1] : ranges[i] , :])

last_subset = df.iloc[ ranges[-1] :, :]
if not last_subset.empty:    
    subsets.append(last_subset)

In [3]: subsets
Out[3]:
   Name  ID  Level  
0  Name1  A    1    
1  Name2  B    2  
2  Name3  C    3 

   Name  ID  Level  
3  Name4  D    1  
4  Name5  E    2

答案 2 :(得分:0)

您可以执行以下操作:

In [513]: df['new'] = df.Level.diff().fillna(0)  
# Create a column 'new' which holds the difference of Level across rows. 
# A negative value here means, level has re-started.

In [514]: df
Out[514]: 
    Name ID  Level  new
0  Name1  A      1  0.0
1  Name2  B      2  1.0
2  Name3  C      3  1.0
3  Name4  D      1 -2.0
4  Name5  E      2  1.0
5  Name6  F      1 -1.0

In [521]: l = df[df.new <0].index  # negative value of column new means, the level has re-started.

In [524]: d = dict() # A dictionary to hold sub-sections of the dataframe

In [530]: for c,i in enumerate(l):
     ...:     if c == 0:
     ...:         d[i] = df.iloc[0:i, :3]
     ...:     else:
     ...:         d[i] = df.iloc[l[c-1]:i, :3]
     ...:         

In [532]: for i in d.keys():  ## Print the multiple smaller dataframes
     ...:     print(d[i])
     ...:     
    Name ID  Level
0  Name1  A      1
1  Name2  B      2
2  Name3  C      3
    Name ID  Level
3  Name4  D      1
4  Name5  E      2

让我知道这是否有帮助。

答案 3 :(得分:0)

这会将所需的Name放在一个地方-

df.groupby(df.groupby(['Level']).cumcount())['Name'].apply(lambda x: ','.join(x))

0    Name1,Name2,Name3
1          Name4,Name5
2                Name6
Name: Name, dtype: object

您现在可以根据需要为每个实体设置Level,或者按照需要的方式在lambda函数中操作apply()

答案 4 :(得分:0)

设置数据框:

df = pd.DataFrame({'Name': ['Name1', 'Name2', 'Name3', 'Name4', 'Name5', 'Name6'],
                   'ID': ['A', 'B', 'C', 'D', 'E', 'F'],
                   'Level': [1, 2, 3, 1, 2, 1]})

使用系列移位查找新组的位置(新级别1),用1标记,然后累加。

grp_markers = (df.Level - df.Level.shift()).fillna(-1).values <= 0
df['grp'] = grp_markers.cumsum()

找到这样的子集:

df[df.grp == 2]

    Name ID  Level    grp
3  Name4  D      1      2
4  Name5  E      2      2

现在您还可以使用grp列进行分组操作...