如何使用申请两个 pandas 列包括列表到 return 索引在一个列中的列表中使用另一列中的元素?
How to use apply for two pandas column including lists to return index in a list in one column using the element in another column?
我有一个 pandas 数据框,其列为 "a" 和 "b"。 a 列有一个值列表作为列值,"b" 列有一个列表,其中可能出现在 "a" 列中的单个值。我想基于 a 列和 b 列创建一个新的 c 列,它具有使用 apply 出现在 a 列值中的 b 中元素的位置值。 (c: (a 中 b 的索引)+1 )
b 列始终是一个包含一个元素或根本没有元素的列表,a 列可以是任意长度,但如果它为空,则 b 列也将为空。 b 列元素应该在 a 列中,我只想找到它在 a 列中第一次出现的位置。
a b c
['1', '2', '5'] ['2'] 2
['2','3','4'] ['4'] 3
['2','3','4'] [] 0
[] [] 0
...
我写了一个 for 循环,它运行良好,但速度很慢:
for i in range(0,len(df)):
if len(df['a'][i])!=0:
df['c'][i]=df['a'][i].index(*df['b'][i])+1
else:
df['c'][i]=0
但是我想使用 apply 使其更快,以下不起作用,任何想法或建议将不胜感激?
df['c']=df['a'].apply(df['a'].index(*df['b']))
通过读取数据以列出数据类型,我能够创建一个应用函数来为 c:
创建值
import io, ast
#a b
#['1','2','5'] ['2']
#['2','3','4'] ['4']
#['2','3','4'] []
#[] []
csvfile=io.StringIO("""a b
['1','2','5'] ['2']
['2','3','4'] ['4']
['2','3','4'] []
[] []""")
df = pd.read_csv(csvfile, sep=' ', converters={'a' : ast.literal_eval, 'b' : ast.literal_eval })
def a_b_index(hm):
if hm.b != []:
return hm.a.index(hm.b[0])
else:
return 0
df['c'] = df.apply(a_b_index, axis=1)
df.c
# a b c
#0 [1, 2, 5] [2] 1
#1 [2, 3, 4] [4] 2
#2 [2, 3, 4] [] 0
#3 [] [] 0
首先,这是使用.apply()
的基本方法。
import pandas as pd
import numpy as np
list_a = [['1', '2', '5'], ['2', '3', '4'], ['2', '3', '4'], []]
list_b = [['2'], ['4'], [], []]
df_1 = pd.DataFrame(data=zip(list_a, list_b), columns=['a', 'b'])
df_1['a'] = df_1['a'].map(lambda x: x if x else np.NaN)
df_1['b'] = df_1['b'].map(lambda x: x[0] if x else np.NaN)
#df_1['b'] = df_1['b'].map(lambda x: next(iter(x), np.NaN))
def calc_c(curr_row: pd.Series) -> int:
if curr_row['a'] is np.NaN or curr_row['b'] is np.NaN:
return 0
else:
return curr_row['a'].index(curr_row['b'])
df_1['c'] = df_1[['a', 'b']].apply(func=calc_c, axis=1)
df_1
结果:
a b c
-- --------------- --- ---
0 ['1', '2', '5'] 2 1
1 ['2', '3', '4'] 4 2
2 ['2', '3', '4'] nan 0
3 nan nan 0
我用 NaN
替换了空列表,我发现它更加地道和实用。
这显然不是理想的解决方案,我会尝试寻找其他解决方案。显然,我们对您的程序和 DataFrame 的了解越多越好。
我有一个 pandas 数据框,其列为 "a" 和 "b"。 a 列有一个值列表作为列值,"b" 列有一个列表,其中可能出现在 "a" 列中的单个值。我想基于 a 列和 b 列创建一个新的 c 列,它具有使用 apply 出现在 a 列值中的 b 中元素的位置值。 (c: (a 中 b 的索引)+1 ) b 列始终是一个包含一个元素或根本没有元素的列表,a 列可以是任意长度,但如果它为空,则 b 列也将为空。 b 列元素应该在 a 列中,我只想找到它在 a 列中第一次出现的位置。
a b c
['1', '2', '5'] ['2'] 2
['2','3','4'] ['4'] 3
['2','3','4'] [] 0
[] [] 0
...
我写了一个 for 循环,它运行良好,但速度很慢:
for i in range(0,len(df)):
if len(df['a'][i])!=0:
df['c'][i]=df['a'][i].index(*df['b'][i])+1
else:
df['c'][i]=0
但是我想使用 apply 使其更快,以下不起作用,任何想法或建议将不胜感激?
df['c']=df['a'].apply(df['a'].index(*df['b']))
通过读取数据以列出数据类型,我能够创建一个应用函数来为 c:
创建值import io, ast
#a b
#['1','2','5'] ['2']
#['2','3','4'] ['4']
#['2','3','4'] []
#[] []
csvfile=io.StringIO("""a b
['1','2','5'] ['2']
['2','3','4'] ['4']
['2','3','4'] []
[] []""")
df = pd.read_csv(csvfile, sep=' ', converters={'a' : ast.literal_eval, 'b' : ast.literal_eval })
def a_b_index(hm):
if hm.b != []:
return hm.a.index(hm.b[0])
else:
return 0
df['c'] = df.apply(a_b_index, axis=1)
df.c
# a b c
#0 [1, 2, 5] [2] 1
#1 [2, 3, 4] [4] 2
#2 [2, 3, 4] [] 0
#3 [] [] 0
首先,这是使用.apply()
的基本方法。
import pandas as pd
import numpy as np
list_a = [['1', '2', '5'], ['2', '3', '4'], ['2', '3', '4'], []]
list_b = [['2'], ['4'], [], []]
df_1 = pd.DataFrame(data=zip(list_a, list_b), columns=['a', 'b'])
df_1['a'] = df_1['a'].map(lambda x: x if x else np.NaN)
df_1['b'] = df_1['b'].map(lambda x: x[0] if x else np.NaN)
#df_1['b'] = df_1['b'].map(lambda x: next(iter(x), np.NaN))
def calc_c(curr_row: pd.Series) -> int:
if curr_row['a'] is np.NaN or curr_row['b'] is np.NaN:
return 0
else:
return curr_row['a'].index(curr_row['b'])
df_1['c'] = df_1[['a', 'b']].apply(func=calc_c, axis=1)
df_1
结果:
a b c
-- --------------- --- ---
0 ['1', '2', '5'] 2 1
1 ['2', '3', '4'] 4 2
2 ['2', '3', '4'] nan 0
3 nan nan 0
我用 NaN
替换了空列表,我发现它更加地道和实用。
这显然不是理想的解决方案,我会尝试寻找其他解决方案。显然,我们对您的程序和 DataFrame 的了解越多越好。