我是 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', :]
当我阅读电子表格时,行和列数是未知的,因此,我需要针对不同的表格大小有一个灵活的解决方案。
答案 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
。然后一些 zip
ping 将多索引转换为两个单独的列表。
(如果你想按名字排序,那么你可以在.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)
使用 melt
和 query
过滤结果 -
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