Создание новых массивов на основе уникальных ключей и условий в Python

avatar
energyMax
8 апреля 2018 в 10:22
59
3
1

Я планирую вычислять большие объемы данных в Python, а не в Excel, но я застрял, так как я знаю команду Excel, и мне очень трудно воспроизвести ее в Python.

По сути, я хотел бы импортировать CSV-файл, определить местоположение столбца C, а затем для всех уникальных значений в столбце A просуммировать все значения в C, которые относятся к условию 1990 < x < 2000 в B

A,B,C
9,1952,125
2,1994,69
3,1973,72
5,1992,85
1,1994,38
1,1994,95
4,1992,29
8,1984,94

Начнем с:

import csv
with open('TestCase.txt', 'rb') as csvfile:
    reader = csv.reader(csvfile, delimiter=',')
    row1 = next(reader)

Вместо того, чтобы писать несколько операторов if, я хотел бы создать новые массивы, состоящие из 0 и 1, а затем суммировать все значения в C.

При других условиях результат будет выглядеть следующим образом

1980<x<1989 94
1990<x<2000 316

Дополнительным бонусом будет общее количество уникальных значений в A, которые представляют общую сумму

UniqueValues    Condition   TotalSum
1   1980<x<1989 94
4   1990<x<2000 316
Источник
Mehrdad Pedramfar
8 апреля 2018 в 10:25
0

Каковы ваши ожидания на выходе? Я могу помочь тебе.

Thomas Junk
8 апреля 2018 в 10:35
0

Должны ли уникальные значения отфильтровываться?

energyMax
8 апреля 2018 в 10:36
0

@mehrdad-pedramfar В конечном счете, я хотел бы увидеть общую сумму значений в C, которые применяют условие, указанное для B. Следующим шагом будет добавление другого условия, например. 1980<x<1989 и посмотреть общую сумму для этого.

energyMax
8 апреля 2018 в 10:51
0

@ThomasJunk Нет. Сумма должна состоять из всех значений.

Mehrdad Pedramfar
8 апреля 2018 в 11:10
0

@energyMax Я опубликовал ответ, он возвращает словарь. тебе нужно что-то еще ? скажите, я обновлю свой ответ.

Ответы (3)

avatar
Mehrdad Pedramfar
8 апреля 2018 в 11:09
0

Вы можете использовать это:

l = list()
d = dict()
with open('TestCase.txt', 'r') as file:
    for line in file:
        l.append(line.rstrip("\n").split(',')) # l=[[9,1952,125],[2,1994,69],...]

    for item in l:
        if 1990 < int(item[1]) < 2000: # The desired condition for colum B 
            d[item[0]] = d[item[0]] + int(item[2]) if item[0] in d else int(item[2])

Словарь d будет уникальным значением A в качестве ключа и суммой C в качестве значения.

avatar
mh70
8 апреля 2018 в 11:17
1
from io import StringIO
import pandas as pd

txt = StringIO("""
A,B,C
9,1952,125
2,1994,69
3,1973,72
5,1992,85
1,1994,38
1,1994,95
4,1992,29
8,1984,94
""")

df = pd.read_csv(txt )

#condition = (df["B"] >1980) & (df["B"] < 1989)
condition = (df["B"] >1990) & (df["B"] < 2000)
df_cond = df[condition]

df_uniq = df_cond.drop_duplicates('A', keep=False)
df_uniq_keep_first = df_cond.drop_duplicates('A', keep="first")
df_uniq_keep_last = df_cond.drop_duplicates('A', keep="last")

sum_dupl = df_cond["C"].sum()
sum_uniq = df_uniq["C"].sum()
sum_uniq_keep_first = df_uniq_keep_first["C"].sum()
sum_uniq_keep_last = df_uniq_keep_last["C"].sum()

print("sum with duplicates  : " + str(sum_dupl))            #316
print("sum pure unique      : " + str(sum_uniq))            #183
print("sum unique keep first: " + str(sum_uniq_keep_first)) #221 
print("sum unique keep last : " + str(sum_uniq_keep_last))  #278
energyMax
8 апреля 2018 в 11:22
0

Это работает, но для условия 1990<x<2000 возвращается 221, а должно быть 316. Учитываются не все значения.

energyMax
8 апреля 2018 в 11:35
0

Спасибо. Как это будет работать, если я импортирую txt? Должен ли я использовать импорт CSV и использовать для него функцию StringIO?

mh70
8 апреля 2018 в 11:39
0

filename = "file_to_import.csv" df = pd.read_csv(filename) Я использовал StringIO только для "преобразования" текстовой переменной в файл для демонстрационного кода. т.е. вам не понадобится from io import StringIO

energyMax
8 апреля 2018 в 11:47
0

Спасибо. Это работает как шарм. Что в этом случае делает команда df_cond.drop_duplicates?

mh70
8 апреля 2018 в 12:27
0

Я попытался удовлетворить ваше требование "учитывать все значения" - так что нет уникальности. Я только что отредактировал демонстрационный код для различных способов обработки дубликатов {False, "first", "last"} . Как вы можете видеть для условия = (df["B"] >1990) & (df["B"] < 2000) способ обработки дубликатов имеет существенные последствия.

avatar
jpp
8 апреля 2018 в 11:16
1

Если вас устраивает использование сторонней библиотеки, ее можно векторизовать через pandas:

import pandas as pd

# read csv file
df = pd.read_csv('file.csv')

# filter column B, group by A, sum C
res = df.loc[df['B'].between(1990, 2000)]\
        .groupby('A')['C'].sum()\
        .reset_index()

Результат:

   A    C
0  1  133
1  2   69
2  4   29
3  5   85