我有一个pandas数据框,我想对一列执行groupby并将自定义函数应用于另一列。但是该功能必须应用于apply列的每两个条目。
a=[2,4,6]
b=[1,3,5,-1,-1,-1,-1]
def replace(iterable, replacements):
i = 0
for e in iterable:
if e == -1 and i < len(replacements):
yield replacements[i]
i += 1
else:
yield e
res = sorted(replace(b, a))
print(res) #=> [-1, 1, 2, 3, 4, 5, 6]
但是目前无法形成apply()的表达式,因为.apply(x)是一个论坛,x将是一个系列,而我无法找到在x(pandas groupby series)上使用索引明智的访问方式对象)。
在广告中,请指导我如何实现此目标。
答案 0 :(得分:1)
IIUC,您可以尝试以下;
df['new_value']=df.vals.shift()
df.groupby(df.index//2)['vals','new_value'].apply(lambda x: pd.Series(list(zip(x.new_value,x.vals))))\
.stack().reset_index(drop=True)
0 (nan, ANZ)
1 (ANZ, ABC)
2 (ABC, SAT)
3 (SAT, SATYA)
4 (SATYA, SQL)
5 (SQL, WER)
6 (WER, DEA)
7 (DEA, KIP)
8 (KIP, FTY)
9 (FTY, TCZ)
编辑:略微修改代码以匹配输出:
a=df.groupby('id')['vals'].apply(lambda x: pd.DataFrame(list(zip(x.shift(),x))))
df['new']=list(zip(a[0],a[1]))
print(df)
id vals new
0 1 ANZ (nan, ANZ)
1 1 ABC (ANZ, ABC)
2 2 SAT (nan, SAT)
3 2 SATYA (SAT, SATYA)
4 2 SQL (SATYA, SQL)
5 3 WER (nan, WER)
6 3 DEA (WER, DEA)
7 3 KIP (DEA, KIP)
8 3 FTY (KIP, FTY)
9 3 TCZ (FTY, TCZ)
答案 1 :(得分:1)
我想建议以其他方式来完成您的任务。
从上一行的vals
开始生成一列
在当前组。我将其命名为prev
。
然后使用apply
调用函数df
中的每一行,替换为
结果在res
列中。
myfunc
获取当前行,并且具有到提取prev
,并
vals
,然后返回结果。
剩下的唯一事情就是删除prev
列。
因此整个脚本如下所示:
import pandas as pd
def myfunc(x):
pr = x.prev
t1 = pr if pd.notnull(pr) else None
t2 = x.vals
return f'myfunc({repr(t1)}, {repr(t2)})'
df = pd.DataFrame({'id':[1,1,2,2,2,3,3,3,3,3], 'vals':
['ANZ', 'ABC', 'SAT', 'SATYA', 'SQL', 'WER', 'DEA', 'KIP', 'FTY', 'TCZ'] })
df['prev'] = df.groupby('id').shift()
df['res'] = df.apply(myfunc, axis=1)
df.drop('prev', axis=1, inplace=True)
当您print(df)
时,您将获得:
id vals res
0 1 ANZ myfunc(None, 'ANZ')
1 1 ABC myfunc('ANZ', 'ABC')
2 2 SAT myfunc(None, 'SAT')
3 2 SATYA myfunc('SAT', 'SATYA')
4 2 SQL myfunc('SATYA', 'SQL')
5 3 WER myfunc(None, 'WER')
6 3 DEA myfunc('WER', 'DEA')
7 3 KIP myfunc('DEA', 'KIP')
8 3 FTY myfunc('KIP', 'FTY')
9 3 TCZ myfunc('FTY', 'TCZ')
答案 2 :(得分:0)
所以我尝试了以下类似方法。
Myfunc用于查找两个字符串之间的字符串相似性,为此我使用了很棒的Fuzzywuzzy库
from fuzzywuzzy import fuzz
def myfunc(x):
x = x.tolist() # converted series to list
y = []
for i in range(0, len(x)):
if i == 0:
y.append(None)
else:
## apply ratio between prev_Row_vals and Current_Row_vals
y.append(fuzz.token_set_ratio(x[i - 1], x[i]) / 10)
return y
## Now the group by and apply/transform function
df['res'] = df.groupby('id')['vals'].transform(lambda x: myfunc(x))
但是我不确定这是否是做这种事情的Python方式。请让我知道是否还有更多的Python方式可以做到这一点。谢谢。