从满足两个条件的 Dataframe 中获取索引和列

时间:2021-05-01 08:03:10

标签: python pandas numpy

我是 Python 和 Pandas 的新手。

我正在尝试通过两个条件过滤字符串数据框,以获取具有满足这两个条件的索引和列的列表或数据框。我从电子表格中获取此数据框,其中每个单元格都是“是”或“不是”。

df = pd.DataFrame([['YES', 'YES', 'NO', 'NO'], ['NO', 'YES', 'NO', 'NO'], ['NO', 'NO', 'NO', 'NO'], ['YES', 'NO', 'NO', 'YES']],

     index=['task1', 'task2', 'task3', 'task4'],

     columns=['David', 'Carol', 'Tony', 'Anna'])

df

            David   Carol   Tony   Anna
taks1       YES     YES     NO     NO
task2       NO      YES     NO     NO
task3       NO      NO      NO     NO
task4       YES     NO      NO     YES

我需要得到这样的东西(两个列表、数据框、二维数组...):

David   task1
David   task4
Carol   task1
Carol   task2
Anna    task4

我使用了 loc,但我无法为所有列扩展过滤器:

active = df.loc[lambda df1: df1['David'] == 'YES', :]

当我阅读电子表格时,行和列数是未知的,因此,我需要针对不同的表格大小有一个灵活的解决方案。

5 个答案:

答案 0 :(得分:1)

可以使用pandas的melt将数据框转换为长格式,然后应用条件

df_long = df.melt(value_vars=['David', 'Carol', 'Tony', 'Anna'], ignore_index=False).reset_index()
df_long.columns = ['Task', 'Name', 'Value']
print(df_long)
     Task   Name Value
0   task1  David   YES
1   task2  David    NO
2   task3  David    NO
3   task4  David   YES
4   task1  Carol   YES
5   task2  Carol   YES
6   task3  Carol    NO
7   task4  Carol    NO
8   task1   Tony    NO
9   task2   Tony    NO
10  task3   Tony    NO
11  task4   Tony    NO
12  task1   Anna    NO
13  task2   Anna    NO
14  task3   Anna    NO
15  task4   Anna   YES
         
df_long.loc[df_long['Value']=='YES', ['Name', 'Task']].reset_index(drop=True)
    Name   Task
0  David  task1
1  David  task4
2  Carol  task1
3  Carol  task2
4   Anna  task4

答案 1 :(得分:1)

<块引用>

需要得到这样的东西(两个列表、数据框、二维数组...):

那怎么样

[*zip(*df[df == "YES"].stack().index)]

给出

[('task1', 'task1', 'task2', 'task4', 'task4'),
 ('David', 'Carol', 'Carol', 'David', 'Anna')]

我们得到 YES 的条目,然后是 stack 索引(任务)旁边的列(名称)。由于我们只对索引感兴趣,取.index。然后一些 zipping 将多索引转换为两个单独的列表。

(如果你想按名字排序,那么你可以在.sort_index(level=1)之后加上.stack()。)

答案 2 :(得分:0)

您的 df 已旋转,因此您想取消旋转您的表格。可以在 Pandas 中使用 .melt() 实现逆透视。这是完整的代码。

>>> import pandas as pd
>>> df = pd.read_clipboard().reset_index().rename(columns={'index':'task'})
>>> print(df)
    task David Carol Tony Anna
0  taks1   YES   YES   NO   NO
1  task2    NO   YES   NO   NO
2  task3    NO    NO   NO   NO
3  task4   YES    NO   NO  YES
>>> df = df.melt(['task'])
>>> print(df.loc[df['value']=='YES', ['variable', 'task']])
   variable   task
0     David  taks1
3     David  task4
4     Carol  taks1
5     Carol  task2
15     Anna  task4

答案 3 :(得分:0)

使用 meltquery 过滤结果 -

result = df.melt(value_vars=['David', 'Carol', 'Tony', 'Anna'], ignore_index=False).query('value == "YES"')['variable']

输出 -

task1    David
task4    David
task1    Carol
task2    Carol
task4     Anna

答案 4 :(得分:0)

s = df.unstack().eq('YES')

基于需求:

多索引数组

s[s].index

MultiIndex([('David', 'task1'),
            ('David', 'task4'),
            ('Carol', 'task1'),
            ('Carol', 'task2'),
            ( 'Anna', 'task4')],
           )

列表

s[s].index.to_list()

[('David', 'task1'),
 ('David', 'task4'),
 ('Carol', 'task1'),
 ('Carol', 'task2'),
 ('Anna', 'task4')]

Numpy 数组

s[s].index.to_numpy()

array([('David', 'task1'), ('David', 'task4'), ('Carol', 'task1'),
       ('Carol', 'task2'), ('Anna', 'task4')], dtype=object)

数据帧

s[s].index.to_frame()
                0       1
David   task1   David   task1
        task4   David   task4
Carol   task1   Carol   task1
        task2   Carol   task2
Anna    task4   Anna    task4

带有列名的正确数据框

我们正在使用 unstack,然后使用 'YES' 获取行。之后,所有的努力都是以所需的格式获得输出。

代码

df.unstack().eq('YES').to_frame().rename(columns={
    (0):'val'}).query('val == True').reset_index().rename(
    columns={'level_0':'index', 'level_1':'value'}).drop('val',1)

输出

    index   value
0   David   task1
1   David   task4
2   Carol   task1
3   Carol   task2
4   Anna    task4