根据列值计数过滤CSV行

时间:2020-08-20 15:10:15

标签: python pandas csv

我对Python还是很陌生,现在我正在执行一项任务,要求我存储从CSV文件中出现少于k次的行。

基本上,CSV文件具有3列。第一列是我必须考虑的部分。因此,例如,如果“ a”在该列中出现的次数少于5次,则我需要挑选这些记录并将其存储在新的CSV文件中。

我设法使用了熊猫的df['column name'].value_counts()来计算每行出现的次数。现在,我坚持如何真正挑选出那些不太频繁的行并进行存储。我有一些想法,例如使用for循环遍历所有行,并使用if检查第一列中的某些数据是否出现少于K次。我无法弄清楚的部分似乎是如何将频率计数与该列中的某些数据相关联。

下面是我的数据文件的屏幕截图 example of my csv data

非常感谢您的帮助!谢谢大家!

2 个答案:

答案 0 :(得分:0)

这是标准库版本:

import csv

THRESHOLD = 5

def get_data(filename, column, threshold=THRESHOLD):
    """Return list of dict of rows where count of the column is smaller than the threshold and the headers of the CSV file"""
    with open(filename, 'r') as f:
        csv_reader = csv.DictReader(f)
        # get all rows where there's NO data in the column
        data = [line for line in csv_reader if not line.get(column)]
        if len(data) < threshold:
            return data, csv_reader.fieldnames

def write_data(filename, data, headers):
    """Write data to a CSV"""
    with open(filename, 'w') as f:
        csv_writer = csv.DictWriter(f, fieldnames=headers)
        csv_writer.writeheader()
        csv_writer.writerows(data)

data, headers = get_data(filename='file.csv', column='a')
write_data(filename='filter.csv', data=data, headers=headers)

答案 1 :(得分:0)

您提到了熊猫,这是一种熊猫方法:

import pandas as pd

# create sample data frame
data = [
    (1, 2, 3),
    (1, 4, 5),
    (1, 6, 7),
    (9, 10, 11),
    (9, 12, 13),
]
df = pd.DataFrame(data, columns=('x', 'y', 'z'))

# keep rows with value in column 'x' appears at most 'ceiling' times
ceiling = 2
low_freq = df['x'].value_counts().loc[lambda x: x <= ceiling].index

# use boolean mask to find rows such that 'x' is in our low_freq list
mask = df['x'].isin(low_freq)

# print results
print(df[mask])

   x   y   z
3  9  10  11
4  9  12  13

# use df[mask].to_csv(...) to write to csv file

更新:

这里是一种“分解”上面代码的方法。例如,low_freq是什么?这样一来,您就可以查看转换中的每个步骤-因此您可以修改/扩展该方法。

df['x']
df['x'].value_counts()
df['x'].value_counts().loc[lambda x: x <= ceiling]
df['x'].value_counts().loc[lambda x: x <= ceiling].index

更新2

显然,过滤逻辑未按预期工作。让我们尝试另一种方法:

import pandas as pd

# create sample data frame
data = [(0, 1, 2, ), (1, 1, 4, ), (2, 1, 6, ),
        (3, 9, 10,), (4, 9, 12,), (5, 7, 21,)]
df = (pd.DataFrame(data, columns=('pos_id', 'device_id', 'base_mac'))
      .set_index('pos_id'))

现在使用groupby()来计算每个device_id的出现次数。此计数进入新列。

df['dev_id_count'] = (df.groupby('device_id')['device_id']
                        .transform('count'))
print(df)

        device_id  base_mac  dev_id_count
pos_id                                   
0               1         2             3
1               1         4             3
2               1         6             3
3               9        10             2
4               9        12             2
5               7        21             1

最后一步是根据此新列进行过滤:

mask = df['dev_id_count'] <= 2
print(df[mask])
# output not shown, to save space