我需要对一些数据进行统计。看看一个值"j"在值"i"旁边。下面的代码大致简化了我需要做的事情,但它包含了我遇到的问题。
假设你有这个数据帧。
import numpy as np
import pandas as pd
a_df=pd.DataFrame({"a_col":np.random.randint(10, size=1000), "b_col":np.random.randint(10, size=1000)})
我生成一个矩阵,它将包含我们的统计数据:
res_matrix=np.zeros((10, 10))
通过查看res_matrix[i][j],我们将知道数字"j"在数字"i"的旁边在我们的数据框架中
我知道"for循环"在熊猫中是不好的,但是,这是一个简化。我为值" I "生成一个子表在这张表上我运行了"value_counts()"在&;b_color &;
for i in a_df["a_col"].unique():
temp_df=a_df[a_df["a_col"]==i]
table_count=temp_df["b_col"].value_counts()
for val,cnt in table_count.iteritems():
res_matrix[i][val]+=int(cnt)
是否有一种有效的方法来填充res_matrix而不改变最顶层的for循环?我在想类似于列表理解的东西,但是我想不起来。
请只注意这两行:
for val,cnt in table_count.iteritems():
res_matrix[i][val]+=int(cnt)
我不能使用groupby,因为我的项目需要对数据框架进行更多的操作。
熊猫中有一个函数crosstab
就是这样做的:
pd.crosstab(a_df['a_col'], a_df['b_col'])
输出:
b_col 0 1 2 3 4 5 6 7 8 9
a_col
0 10 10 10 12 14 9 10 5 13 16
1 16 9 13 14 14 8 4 11 9 12
2 10 8 12 13 9 12 13 7 10 5
3 11 7 10 17 6 9 6 8 7 14
4 9 8 4 5 7 13 12 8 11 6
5 14 9 8 15 6 10 12 9 7 9
6 11 13 10 9 7 5 8 11 13 21
7 8 9 11 8 8 10 11 15 10 12
8 6 17 11 4 12 9 6 10 10 13
9 12 6 14 3 11 11 7 5 14 14
更新:如果由于其他原因必须保留外循环,则可以在循环内的res_matrix
中设置值:
res_matrix = np.zeros((10, 10))
for i in a_df["a_col"].unique():
temp_df=a_df[a_df["a_col"]==i]
table_count=temp_df["b_col"].value_counts()
# set values in res_matrix
res_matrix[i, table_count.index] = table_count
不要循环,这是缓慢的如果你认为有一个很好的理由循环,请解释它并提供一个适当的例子。
这是另一个方法。
你可以groupby
两个列得到组size
,然后unstack
得到二维形状:
a_df.groupby(['a_col', 'b_col']).size().unstack()
输出:
b_col 0 1 2 3 4 5 6 7 8 9
a_col
0 16 2 4 11 9 13 11 11 8 6
1 10 12 7 6 6 11 10 8 2 12
2 9 12 10 22 12 13 8 11 9 8
3 13 11 11 14 7 11 9 7 8 14
4 14 7 17 5 8 6 15 8 11 8
5 10 12 7 14 6 16 11 12 6 8
6 13 10 9 12 11 14 8 10 6 8
7 9 12 12 9 11 9 8 14 5 12
8 7 8 9 8 10 14 9 8 8 18
9 13 6 13 11 13 11 8 7 11 11