如何计算两列中任何一列的出现次数

时间:2016-09-12 13:23:09

标签: python pandas

我有一个简单的问题。我有一个包含两列的数据框df。对于在这两列中出现的每个字符串,我想计算在任一列中都有符号的行数。

E.g。

g k
a h
c i
j e
d i
i h
b b
d d
i a
d h

以下代码有效但效率很低。

for elem in set(df.values.flat):
    print elem, len(df.loc[(df[0] == elem) | (df[1] == elem)])


a 2
c 1
b 1
e 1
d 3
g 1
i 4
h 3
k 1
j 1

然而,这是非常低效的,我的数据帧很大。效率低下来自于分别为df中的每个不同符号调用df.loc[(df[0] == elem) | (df[1] == elem)]

有这么快的方法吗?

2 个答案:

答案 0 :(得分:2)

您可以使用loc过滤掉'col2'的行级匹配,将已过滤的'col2'值附加到'col1',然后调用value_counts:< / p>

counts = df['col1'].append(df.loc[df['col1'] != df['col2'], 'col2']).value_counts()

结果输出:

i    4
d    3
h    3
a    2
j    1
k    1
c    1
g    1
b    1
e    1

注意:如果您希望输出按字母顺序显示,可以将.sort_index()添加到计数代码的末尾。

<强>计时

使用以下设置生成更大的样本数据集:

from string import ascii_lowercase

n = 10**5
data = np.random.choice(list(ascii_lowercase), size=(n,2))
df = pd.DataFrame(data, columns=['col1', 'col2'])

def edchum(df):
    vals = np.unique(df.values)
    count = np.maximum(df['col1'].str.get_dummies().reindex_axis(vals, axis=1).fillna(0), df['col2'].str.get_dummies().reindex_axis(vals, axis=1).fillna(0)).sum()
    return count

我得到以下时间:

%timeit df['col1'].append(df.loc[df['col1'] != df['col2'], 'col2']).value_counts()
10 loops, best of 3: 19.7 ms per loop

%timeit edchum(df)
1 loop, best of 3: 3.81 s per loop

答案 1 :(得分:1)

好吧这比我想象的要复杂得多,不确定这会如何扩展,但是如果你有很多重复值,那么它会比你当前的方法更有效,基本上我们可以使用str.get_dummies并重新索引结果中的列为所有唯一值生成dummies df,然后我们可以在2 dfs和np.maximal上使用sum

In [77]:
t="""col1 col2
g k
a h
c i
j e
d i
i h
b b
d d
i a
d h"""
df = pd.read_csv(io.StringIO(t), delim_whitespace=True)
np.maximum(df['col1'].str.get_dummies().reindex_axis(vals, axis=1).fillna(0), df['col2'].str.get_dummies().reindex_axis(vals, axis=1).fillna(0)).sum()

Out[77]:
a    2
b    1
c    1
d    3
e    1
g    1
h    3
i    4
j    1
k    1
dtype: float64
这里的vals只是唯一的值:

In [80]:
vals = np.unique(df.values)
vals

Out[80]:
array(['a', 'b', 'c', 'd', 'e', 'g', 'h', 'i', 'j', 'k'], dtype=object)