Groupby并在Python中的两列中查找相似或相同的项
对于如下数据帧,如果Groupby并在Python中的两列中查找相似或相同的项,python,pandas,dataframe,Python,Pandas,Dataframe,对于如下数据帧,如果name2中的字符串与name1中的字符串在类型的每组中大致相似或相同,则返回Y,否则返回N id type name1 name2 0 1 A James B. James 1 2 A Keras Steven 2 3 A NaN Keras 3 4 B Jack Lucy 4 5 B Lucy Jack 5
name2
中的字符串与name1
中的字符串在类型的每组中大致相似或相同,则返回Y
,否则返回N
id type name1 name2
0 1 A James B. James
1 2 A Keras Steven
2 3 A NaN Keras
3 4 B Jack Lucy
4 5 B Lucy Jack
5 6 C Jasica Hoverd
6 7 C Steven Jasica
7 8 C NaN Steven L.
id type name1 name2 result
0 1 A James B. James Y
1 2 A Keras Steven N
2 3 A NaN Keras Y
3 4 B Jack Lucy Y
4 5 B Lucy Jack Y
5 6 C Jasica Hoverd N
6 7 C Steven Jasica Y
7 8 C NaN Steven L. Y
预期的结果是这样的,例如,在type
A
中,来自name2
的James
具有相似的值James B.
在name1
中,Keras
在name2
和name1
中具有相同的值,因此它们在结果中都返回Y
。虽然Steven
在name1
中不存在,所以返回N
id type name1 name2
0 1 A James B. James
1 2 A Keras Steven
2 3 A NaN Keras
3 4 B Jack Lucy
4 5 B Lucy Jack
5 6 C Jasica Hoverd
6 7 C Steven Jasica
7 8 C NaN Steven L.
id type name1 name2 result
0 1 A James B. James Y
1 2 A Keras Steven N
2 3 A NaN Keras Y
3 4 B Jack Lucy Y
4 5 B Lucy Jack Y
5 6 C Jasica Hoverd N
6 7 C Steven Jasica Y
7 8 C NaN Steven L. Y
有人能帮忙吗?多谢各位
如果查找相似值太复杂而无法实现,则只查找相同的值并返回Y
就可以了。如果没有相似性,则更简单:
mask = df.groupby('type', group_keys=False).apply(lambda x: x['name2'].isin(x['name1']))
df['new'] = np.where(mask, 'Y','N')
print (df)
id type name1 name2 new
0 1 A James B. James N
1 2 A Keras Steven N
2 3 A NaN Keras Y
3 4 B Jack Lucy Y
4 5 B Lucy Jack Y
5 6 C Jasica Hoverd N
6 7 C Steven Jasica Y
7 8 C NaN Steven L. N
与split基本相似:
mask = (df.assign(name1 = df['name1'].fillna('|').astype(str).str.split().str[0],
name2 = df['name2'].astype(str).str.split().str[0])
.groupby('type', group_keys=False)
.apply(lambda x: x['name2'].isin(x['name1'])))
df['new'] = np.where(mask, 'Y','N')
print (df)
id type name1 name2 new
0 1 A James B. James Y
1 2 A Keras Steven N
2 3 A NaN Keras Y
3 4 B Jack Lucy Y
4 5 B Lucy Jack Y
5 6 C Jasica Hoverd N
6 7 C Steven Jasica Y
7 8 C NaN Steven L. Y
为了更好地匹配相似性,可以使用SequenceMatcher
进行比率匹配,并通过treshold进行过滤,例如,此处通过0.5
:
from difflib import SequenceMatcher
def f(x):
comp = [any(SequenceMatcher(None, a, b).ratio() > .5
for a in x['name1'].fillna('_'))
for b in x['name2']]
return pd.Series(comp, index=x.index)
mask = df.groupby('type', group_keys=False).apply(f)
df['new'] = np.where(mask, 'Y','N')
print (df)
id type name1 name2 new
0 1 A James B. James Y
1 2 A Keras Steven N
2 3 A NaN Keras Y
3 4 B Jack Lucy Y
4 5 B Lucy Jack Y
5 6 C Jasica Hoverd N
6 7 C Steven LA. Jasica Y
7 8 C NaN Steven L. Y
如果没有相似性,则更为简单:
mask = df.groupby('type', group_keys=False).apply(lambda x: x['name2'].isin(x['name1']))
df['new'] = np.where(mask, 'Y','N')
print (df)
id type name1 name2 new
0 1 A James B. James N
1 2 A Keras Steven N
2 3 A NaN Keras Y
3 4 B Jack Lucy Y
4 5 B Lucy Jack Y
5 6 C Jasica Hoverd N
6 7 C Steven Jasica Y
7 8 C NaN Steven L. N
与split基本相似:
mask = (df.assign(name1 = df['name1'].fillna('|').astype(str).str.split().str[0],
name2 = df['name2'].astype(str).str.split().str[0])
.groupby('type', group_keys=False)
.apply(lambda x: x['name2'].isin(x['name1'])))
df['new'] = np.where(mask, 'Y','N')
print (df)
id type name1 name2 new
0 1 A James B. James Y
1 2 A Keras Steven N
2 3 A NaN Keras Y
3 4 B Jack Lucy Y
4 5 B Lucy Jack Y
5 6 C Jasica Hoverd N
6 7 C Steven Jasica Y
7 8 C NaN Steven L. Y
为了更好地匹配相似性,可以使用SequenceMatcher
进行比率匹配,并通过treshold进行过滤,例如,此处通过0.5
:
from difflib import SequenceMatcher
def f(x):
comp = [any(SequenceMatcher(None, a, b).ratio() > .5
for a in x['name1'].fillna('_'))
for b in x['name2']]
return pd.Series(comp, index=x.index)
mask = df.groupby('type', group_keys=False).apply(f)
df['new'] = np.where(mask, 'Y','N')
print (df)
id type name1 name2 new
0 1 A James B. James Y
1 2 A Keras Steven N
2 3 A NaN Keras Y
3 4 B Jack Lucy Y
4 5 B Lucy Jack Y
5 6 C Jasica Hoverd N
6 7 C Steven LA. Jasica Y
7 8 C NaN Steven L. Y
输出
id type name1 name2 result
0 1 A James B. James Y
1 2 A Keras Steven N
2 3 A NaN Keras Y
3 4 B Jack Lucy Y
4 5 B Lucy Jack Y
5 6 C Jasica Hoverd N
6 7 C Steven Jasica Y
7 8 C NaN Steven L. Y
输出
id type name1 name2 result
0 1 A James B. James Y
1 2 A Keras Steven N
2 3 A NaN Keras Y
3 4 B Jack Lucy Y
4 5 B Lucy Jack Y
5 6 C Jasica Hoverd N
6 7 C Steven Jasica Y
7 8 C NaN Steven L. Y
您的解决方案与他的预期输出不匹配谢谢,但我得到了一个相同的错误:AttributeError:只能使用带字符串值的.str访问器,它在pandas
@ahbon中使用np.object\dtype-问题是如果强制转换到字符串,然后将nan
s与nan
s匹配,因为字符串'nan'='nan'
。因此,为了避免匹配,有必要将至少转换为其他内容,@ahbon-使用SequenceMatcher
@ahbon-编辑另一个通用解决方案的答案-是的,因此另一个答案是关于拆分的,我的第二个答案是关于拆分的,因此无法使用。需要更一般的匹配相似性的最后一个答案,如果需要匹配,如Steven L.到Steven LA。
或Steven到Stevens
您的解决方案与他预期的输出不匹配谢谢,但我得到了一个相同的错误:AttributeError:只能使用带字符串值的.str访问器,在pandas
@ahbon中使用np.object\dtype-问题是如果对字符串进行强制转换,则将nan
s与nan
s匹配,因为字符串'nan'='nan'
。因此,为了避免匹配,有必要将至少转换为其他内容,@ahbon-使用SequenceMatcher
@ahbon-编辑另一个通用解决方案的答案-是的,因此另一个答案是关于拆分的,我的第二个答案是关于拆分的,因此无法使用。需要更一般匹配相似性的最后一个答案,如果需要匹配,如Steven L.到Steven LA.
或Steven到Stevens
谢谢,但我的实际数据AttributeError:只能使用带字符串值的.str访问器,在pandas
@iamklaus中使用np.object\dtype的-它匹配NaN
s witnNaNs
-无法转换both@jezrael怀疑是否会放弃它们,继续向str施法,然后进行分割。一次转换,另一次移除,检查我的回答谢谢,但是我的实际数据AttributeError:只能使用带字符串值的.str访问器,它在pandas
@iamklaus中使用np.object\dtype-它匹配NaN
s witnNaNs
-无法转换both@jezrael怀疑是否会放弃它们,然后向str全部施放,然后进行分割。一个皈依者,另外,请检查我的答案