使用 pandas 和集合计算每列中某些值的数量
Counting number of certain values in each column using pandas and collections
我有一个包含 9 列和 6 行的 txt 文件。前 8 列是以下值之一:“1”、“2”和“3”。我将这些列命名为“A”到“H”。我将最后一列命名为:“class”。
最后一列是名称:“HIGH”。这是 txt 文件 (data.txt):
1,1,1,1,2,1,1,3,HIGH
1,1,1,2,2,1,1,3,HIGH
1,1,1,1,1,1,1,3,HIGH
1,1,1,2,1,1,1,3,HIGH
1,1,1,3,2,1,1,3,HIGH
1,1,1,2,1,2,1,3,HIGH
我正在尝试计算每列中每个值的数量并打印一个列表,该列表应包含 3 个组件,包括该列中“1”、“2”和“3”值的数量 分别。例如,在第一列(例如 A)中,所有值都是“1”。我希望得到:A:[6,0,0]。对于所有值为“3”的第 8 列(例如 H),我希望得到:H : [0,0,6] 或对于第四列(例如 D)我有两个“1”,三个“2”和一个“3”。所以我期望:D:[2,3,1]。我尝试使用 pandas
和 collection
来完成它。这是我所做的:
import pandas as pd
from collections import Counter
df = pd.read_csv('data.txt')
df.columns = ['A','B','C','D','E','F','G','H','class']
X = df.ix[:, 0:8].values
y = df.ix[:, 8].values
deg = ['HIGH']
names = ['A','B','C','D','E','F','G','H']
for j in range(0, 8):
freqs = Counter(X[y == deg[0], j])
print(names[j],':',list(freqs.values()))
以上代码的输出是空列表。这是它 returns:
A : []
B : []
C : []
D : []
E : []
F : []
G : []
H : []
如何修改上面的代码来得到我想要的?
谢谢!
使用pandas.Series.value_counts
df.loc[:, :"H"].apply(pd.Series.value_counts).fillna(0).to_dict("l")
输出:
{'A': [6.0, 0.0, 0.0],
'B': [6.0, 0.0, 0.0],
'C': [6.0, 0.0, 0.0],
'D': [2, 3, 1],
'E': [3.0, 3.0, 0.0],
'F': [5.0, 1.0, 0.0],
'G': [6.0, 0.0, 0.0],
'H': [0.0, 0.0, 6.0]}
集合的解决方案是 select 所有没有最后的列,将 Counter
转换为 Series
,因此输出为 DataFrame
,用 DataFrame.fillna
, convert values to integers and last to dictionary by DataFrame.to_dict
替换缺失值:
from collections import Counter
d = (df.iloc[:, :-1].apply(lambda x: pd.Series(Counter(x)))
.fillna(0)
.astype(int)
.to_dict("list"))
print (d)
{'A': [6, 0, 0], 'B': [6, 0, 0],
'C': [6, 0, 0], 'D': [1, 4, 1],
'E': [3, 3, 0], 'F': [5, 1, 0],
'G': [6, 0, 0], 'H': [0, 0, 6]}
只有 pandas 解决方案 pandas.value_counts
:
d = (df.iloc[:, :-1].apply(pd.value_counts)
.fillna(0)
.astype(int)
.to_dict("list"))
print (d)
{'A': [6, 0, 0], 'B': [6, 0, 0],
'C': [6, 0, 0], 'D': [2, 3, 1],
'E': [3, 3, 0], 'F': [5, 1, 0],
'G': [6, 0, 0], 'H': [0, 0, 6]}
在 python 内工作,因为您的最终结果是字典:
from string import ascii_uppercase
from collections import Counter, defaultdict
from itertools import chain, product
import csv
d = defaultdict(list)
fieldnames = ascii_uppercase[:9]
# test.csv is your file above
with open('test.csv') as csvfile:
reader = csv.DictReader(csvfile, fieldnames = list(fieldnames))
reader = Counter(chain.from_iterable(row.items() for row in reader))
for col, value in product(fieldnames, ("1","2","3")):
if col != fieldnames[-1]:
d[col].append(reader.get((col,value), 0))
打印(d)
defaultdict(list,
{'A': [6, 0, 0],
'B': [6, 0, 0],
'C': [6, 0, 0],
'D': [2, 3, 1],
'E': [3, 3, 0],
'F': [5, 1, 0],
'G': [6, 0, 0],
'H': [0, 0, 6]})
定义以下函数:
def cntInts(col):
vc = col.value_counts()
return [ vc.get(i, 0) for i in range(1,4) ]
然后应用它并打印结果:
for k, v in df.loc[:, 'A':'H'].apply(cntInts).iteritems():
print(f'{k}: {v}')
对于你的数据样本,我得到了:
A: [6, 0, 0]
B: [6, 0, 0]
C: [6, 0, 0]
D: [2, 3, 1]
E: [3, 3, 0]
F: [5, 1, 0]
G: [6, 0, 0]
H: [0, 0, 6]
或者调用就足够了:
df.loc[:, 'A':'H'].apply(cntInts)
这次的结果是 系列 ,打印结果为:
A [6, 0, 0]
B [6, 0, 0]
C [6, 0, 0]
D [2, 3, 1]
E [3, 3, 0]
F [5, 1, 0]
G [6, 0, 0]
H [0, 0, 6]
dtype: object
编辑
根据您的评论,我认为您的数据有问题。
追根溯源:
定义一个字符串变量:
txt = '''1,1,1,1,2,1,1,3,HIGH
1,1,1,2,2,1,1,3,HIGH
1,1,1,1,1,1,1,3,HIGH
1,1,1,2,1,1,1,3,HIGH
1,1,1,3,2,1,1,3,HIGH
1,1,1,2,1,2,1,3,HIGH'''
运行:
import io
df = pd.read_csv(io.StringIO(txt), names=['A','B','C','D','E','F','G','H','class'])
运行 我的代码在 我的 数据上。结果应该和预期的一样。
然后再次阅读你的输入文件(也进入df)和运行我的代码。
您的数据和我的数据之间可能存在一些差异。
特别是在你的输入文件中寻找任何额外的空间,
还要检查列类型(在 read_csv 之后)。
我有一个包含 9 列和 6 行的 txt 文件。前 8 列是以下值之一:“1”、“2”和“3”。我将这些列命名为“A”到“H”。我将最后一列命名为:“class”。 最后一列是名称:“HIGH”。这是 txt 文件 (data.txt):
1,1,1,1,2,1,1,3,HIGH
1,1,1,2,2,1,1,3,HIGH
1,1,1,1,1,1,1,3,HIGH
1,1,1,2,1,1,1,3,HIGH
1,1,1,3,2,1,1,3,HIGH
1,1,1,2,1,2,1,3,HIGH
我正在尝试计算每列中每个值的数量并打印一个列表,该列表应包含 3 个组件,包括该列中“1”、“2”和“3”值的数量 分别。例如,在第一列(例如 A)中,所有值都是“1”。我希望得到:A:[6,0,0]。对于所有值为“3”的第 8 列(例如 H),我希望得到:H : [0,0,6] 或对于第四列(例如 D)我有两个“1”,三个“2”和一个“3”。所以我期望:D:[2,3,1]。我尝试使用 pandas
和 collection
来完成它。这是我所做的:
import pandas as pd
from collections import Counter
df = pd.read_csv('data.txt')
df.columns = ['A','B','C','D','E','F','G','H','class']
X = df.ix[:, 0:8].values
y = df.ix[:, 8].values
deg = ['HIGH']
names = ['A','B','C','D','E','F','G','H']
for j in range(0, 8):
freqs = Counter(X[y == deg[0], j])
print(names[j],':',list(freqs.values()))
以上代码的输出是空列表。这是它 returns:
A : []
B : []
C : []
D : []
E : []
F : []
G : []
H : []
如何修改上面的代码来得到我想要的? 谢谢!
使用pandas.Series.value_counts
df.loc[:, :"H"].apply(pd.Series.value_counts).fillna(0).to_dict("l")
输出:
{'A': [6.0, 0.0, 0.0],
'B': [6.0, 0.0, 0.0],
'C': [6.0, 0.0, 0.0],
'D': [2, 3, 1],
'E': [3.0, 3.0, 0.0],
'F': [5.0, 1.0, 0.0],
'G': [6.0, 0.0, 0.0],
'H': [0.0, 0.0, 6.0]}
集合的解决方案是 select 所有没有最后的列,将 Counter
转换为 Series
,因此输出为 DataFrame
,用 DataFrame.fillna
, convert values to integers and last to dictionary by DataFrame.to_dict
替换缺失值:
from collections import Counter
d = (df.iloc[:, :-1].apply(lambda x: pd.Series(Counter(x)))
.fillna(0)
.astype(int)
.to_dict("list"))
print (d)
{'A': [6, 0, 0], 'B': [6, 0, 0],
'C': [6, 0, 0], 'D': [1, 4, 1],
'E': [3, 3, 0], 'F': [5, 1, 0],
'G': [6, 0, 0], 'H': [0, 0, 6]}
只有 pandas 解决方案 pandas.value_counts
:
d = (df.iloc[:, :-1].apply(pd.value_counts)
.fillna(0)
.astype(int)
.to_dict("list"))
print (d)
{'A': [6, 0, 0], 'B': [6, 0, 0],
'C': [6, 0, 0], 'D': [2, 3, 1],
'E': [3, 3, 0], 'F': [5, 1, 0],
'G': [6, 0, 0], 'H': [0, 0, 6]}
在 python 内工作,因为您的最终结果是字典:
from string import ascii_uppercase
from collections import Counter, defaultdict
from itertools import chain, product
import csv
d = defaultdict(list)
fieldnames = ascii_uppercase[:9]
# test.csv is your file above
with open('test.csv') as csvfile:
reader = csv.DictReader(csvfile, fieldnames = list(fieldnames))
reader = Counter(chain.from_iterable(row.items() for row in reader))
for col, value in product(fieldnames, ("1","2","3")):
if col != fieldnames[-1]:
d[col].append(reader.get((col,value), 0))
打印(d)
defaultdict(list,
{'A': [6, 0, 0],
'B': [6, 0, 0],
'C': [6, 0, 0],
'D': [2, 3, 1],
'E': [3, 3, 0],
'F': [5, 1, 0],
'G': [6, 0, 0],
'H': [0, 0, 6]})
定义以下函数:
def cntInts(col):
vc = col.value_counts()
return [ vc.get(i, 0) for i in range(1,4) ]
然后应用它并打印结果:
for k, v in df.loc[:, 'A':'H'].apply(cntInts).iteritems():
print(f'{k}: {v}')
对于你的数据样本,我得到了:
A: [6, 0, 0]
B: [6, 0, 0]
C: [6, 0, 0]
D: [2, 3, 1]
E: [3, 3, 0]
F: [5, 1, 0]
G: [6, 0, 0]
H: [0, 0, 6]
或者调用就足够了:
df.loc[:, 'A':'H'].apply(cntInts)
这次的结果是 系列 ,打印结果为:
A [6, 0, 0]
B [6, 0, 0]
C [6, 0, 0]
D [2, 3, 1]
E [3, 3, 0]
F [5, 1, 0]
G [6, 0, 0]
H [0, 0, 6]
dtype: object
编辑
根据您的评论,我认为您的数据有问题。
追根溯源:
定义一个字符串变量:
txt = '''1,1,1,1,2,1,1,3,HIGH 1,1,1,2,2,1,1,3,HIGH 1,1,1,1,1,1,1,3,HIGH 1,1,1,2,1,1,1,3,HIGH 1,1,1,3,2,1,1,3,HIGH 1,1,1,2,1,2,1,3,HIGH'''
运行:
import io df = pd.read_csv(io.StringIO(txt), names=['A','B','C','D','E','F','G','H','class'])
运行 我的代码在 我的 数据上。结果应该和预期的一样。
然后再次阅读你的输入文件(也进入df)和运行我的代码。 您的数据和我的数据之间可能存在一些差异。 特别是在你的输入文件中寻找任何额外的空间, 还要检查列类型(在 read_csv 之后)。