python - Pandas 数据框 : select multiple rows based on entries in other rows

标签 python python-3.x pandas dataframe

根据评论更新(2018/11/06):

这是我正在使用的实际 .csv 文件(从原始帖子稍微扩展)。假设我无法更改 .csv 文件的格式,我该如何

(a) 获取参加“测试 1”的学生和分数的数组?

(b) 重构数据以使其更容易获取 (a)

Year,2017
Class,A
Test,1
Bob,71
Cathy,72
,
Test,2
Steve,73
Janet,74
,
,
Class,B
Test,1
Jim,75
Pam,76
,
Test,2
Linus,77
Lucy,78
,
,
,
Year,2018
Class,A
Test,1
Charles,79
Cindy,80
,
Test,2
Stanley,81
Kari,82
,
,
Class,B
Test,1
Duke,83
Amy,84
,
Test,2
Craig,85
Valerie,86

------------------------------------------------------------ -----------------

原帖:

假设我有以下数据框:

import pandas as pd
data = [['Class A'],['Test 1'],['Bob',87],['Cathy',88],['Test 2'],['Steve',82],['Janet',81],['Class B'],['Test 1'],['Jim',92],['Pam',95],['Test 2'],['Linus',73],['Lucy',70]]
df = pd.DataFrame(data)
print(df)

结果

          0     1
0   Class A   NaN
1    Test 1   NaN
2       Bob  87.0
3     Cathy  88.0
4    Test 2   NaN
5     Steve  82.0
6     Janet  81.0
7   Class B   NaN
8    Test 1   NaN
9       Jim  92.0
10      Pam  95.0
11   Test 2   NaN
12    Linus  73.0
13     Lucy  70.0

有没有办法选择参加测试 1 的两个类(class)的学生获得的分数?即,

Bob  87.0
Cathy  88.0
Jim  92.0
Pam  95.0

谢谢!

最佳答案

编辑: 将数据从给定的源文件导入结构化数据框,以便能够访问方便的分析功能:

这个想法是迭代文本文件的行。
- 我假设每行由两个逗号分隔的字符串组成。
- 第一个字符串为“Year”、“Class”和“Test”之一的每一行仅用于更新保存这三个值的当前集合的字典。
- 所有其他行用于将其数据与年份、类(class)和测试信息一起附加到列表数据
- 除了第一个字符串是空字符串的那些行。

with open('no_csv.txt', 'r') as f:
    Idx = {'Year': None, 'Class': None, 'Test': None}
    data = []
    for line in f:
        key, value = line.strip().split(',')
        if key in Idx.keys():
            Idx[key] = value
        elif key != '':
            data.append(list(Idx.values()) + [key, value])
df = pd.DataFrame(data, columns=['Year', 'Class', 'Test', 'Name', 'Points'])


df

    Year Class Test     Name Points
0   2017     A    1      Bob     71
1   2017     A    1    Cathy     72
2   2017     A    2    Steve     73
3   2017     A    2    Janet     74
4   2017     B    1      Jim     75
5   2017     B    1      Pam     76
6   2017     B    2    Linus     77
7   2017     B    2     Lucy     78
8   2018     A    1  Charles     79
9   2018     A    1    Cindy     80
10  2018     A    2  Stanley     81
11  2018     A    2     Kari     82
12  2018     B    1     Duke     83
13  2018     B    1      Amy     84
14  2018     B    2    Craig     85
15  2018     B    2  Valerie     86

请注意,此代码依赖于字典中的有序键,这是从 Python 3.7 开始在普通 dict 中实现的。为了在 Python 3.6 或更低版本中保证这一点,应该使用 OrderedDict:

from collections import OrderedDict
Idx = OrderedDict(Year=None, Class=None, Test=None)
<小时/>

重组以更好地处理

我建议重组您的数据框。如果您严格定义列的含义,您会得到例如像这样:

data = [
['Class A', 'Test 1', 'Bob', 87],
['Class A', 'Test 1', 'Cathy', 88],
['Class A', 'Test 2', 'Steve', 82],
['Class A', 'Test 2', 'Janet', 81],
['Class B', 'Test 1', 'Jim', 92],
['Class B', 'Test 1', 'Pam', 95],
['Class B', 'Test 2', 'Linus', 73],
['Class B', 'Test 2', 'Lucy', 70]]

df = pd.DataFrame(data)

         0       1      2   3
0  Class A  Test 1    Bob  87
1  Class A  Test 1  Cathy  88
2  Class A  Test 2  Steve  82
3  Class A  Test 2  Janet  81
4  Class B  Test 1    Jim  92
5  Class B  Test 1    Pam  95
6  Class B  Test 2  Linus  73
7  Class B  Test 2   Lucy  70

在数据框中具有此结构,您只需询问所有行,其中测试列是测试1:

df[df[1]=='Test 1']

         0       1      2   3
0  Class A  Test 1    Bob  87
1  Class A  Test 1  Cathy  88
4  Class B  Test 1    Jim  92
5  Class B  Test 1    Pam  95

使用列名称简化数据

由于 pandas 数据框可能有列名称,您甚至可以通过为列指定一个有意义的名称来描述存储在其中的数据,从而提高其可读性并减少冗余数据:

data = [
['A', 1, 'Bob', 87],
['A', 1, 'Cathy', 88],
['A', 2, 'Steve', 82],
['A', 2, 'Janet', 81],
['B', 1, 'Jim', 92],
['B', 1, 'Pam', 95],
['B', 2, 'Linus', 73],
['B', 2, 'Lucy', 70]]

df = pd.DataFrame(data, columns=['Class', 'Test', 'Name', 'Points'])

df[df.Test==1]

  Class  Test   Name  Points
0     A     1    Bob      87
1     A     1  Cathy      88
4     B     1    Jim      92
5     B     1    Pam      95

通过这样做,您将获得进一步分析的收获...<​​/strong>

像这样的数据结构可以访问非常方便的 pandas 函数,以解决您可能想回答的下一个明显问题,例如:

每个类(class)每次测试的平均分数是多少?

df.groupby(['Class', 'Test']).mean()

            Points
Class Test        
A     1       87.5
      2       81.5
B     1       93.5
      2       71.5

每个类(class)每次测试谁是最好的?

df.loc[df.groupby(['Class', 'Test']).Points.idxmax()]

  Class  Test   Name  Points
1     A     1  Cathy      88
2     A     2  Steve      82
5     B     1    Pam      95
6     B     2  Linus      73

关于python - Pandas 数据框 : select multiple rows based on entries in other rows,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53146762/

相关文章:

python - Doctests 在 C 扩展和 Python3 上因 UnicodeDecodeError 而失败

Python:将静态方法分配给类变量会出错

python - 在列表理解中理解这个 if 语句

python - 仅当字符串匹配时才在 python 中连接字符串

python - 从单个列创建多个列

python - 列 Pandas 的百分比

python - 在控制台中打印,但在格式化为 CSV 时不打印

python - 在 ubuntu 上安装 PyQt5 时未满足的依赖关系

python - 无法调用Python C扩展中的方法

python - 从服务器获取表名