Mam ramkę danych z dwiema kolumnami:
import pandas as pd
data={'A':['x','y','z','r','x','z'],'B':[1,2,3,4,1,7]}
df=pd.DataFrame(data)
To mnie dostaje:
A | B
x | 1
y | 2
z | 3
r | 4
x | 1
z | 7
Następnie lista z n listami dwóch elementów:
list_of_lists=[['x',1],['x',4],['z',3],['y',1]]
Chcę się dowiedzieć, czy element 1. każdej sub_list pasuje do kolumny A , a drugi element do kolumny B , otrzymując coś takiego:
A | B | Match
x | 1 | True
y | 2 | False
z | 3 | True
r | 4 | False
x | 1 | True
z | 7 | False
Pomyślałem o stworzeniu dwóch list dla każdego elementu list i zrobieniu czegoś takiego jak np. Gdzie z obydwoma warunkami, ale musi być bardziej przejrzysty sposób.
5 odpowiedzi
Możesz spróbować:
>>> df2 = pd.DataFrame(data = list_of_lists, columns = df.columns)
# less readable but slightly faster
# df2 = pd.DataFrame(dict(zip(['A','B'],zip(*list_of_lists))))
>>> df['Match'] = np.isin(df, df2).all(1)
>>> df
A B Match
0 x 1 True
1 y 2 False
2 z 3 True
3 r 4 False
4 x 1 True
5 z 7 False
Możesz użyć metody apply
:
df['Match'] = df.apply(lambda r: r.tolist() in list_of_lists, axis=1)
df
A B Match
0 x 1 True
1 y 2 False
2 z 3 True
3 r 4 False
4 x 1 True
5 z 7 False
Aby to zrozumieć, możesz wykonać krok pośredni i sprawdzić wynik:
df['temp'] = df.apply(lambda r: r.tolist(), axis=1)
df
A B temp
0 x 1 [x, 1]
1 y 2 [y, 2]
2 z 3 [z, 3]
3 r 4 [r, 4]
4 x 1 [x, 1]
5 z 7 [z, 7]
Następnie
df['Match'] = df.apply(lambda r: r['temp'] in list_of_lists, axis=1)
df
A B temp Match
0 x 1 [x, 1] True
1 y 2 [y, 2] False
2 z 3 [z, 3] True
3 r 4 [r, 4] False
4 x 1 [x, 1] True
5 z 7 [z, 7] False
Użyj DataFrame.merge
z helperem DataFrame
z lewym złączeniem i parametrem indicator=True, a następnie porównaj wartość both
:
df1 = df.merge(pd.DataFrame(list_of_lists, columns=df.columns), how='left', indicator=True)
df['Match'] = df1['_merge'].eq('both')
print (df)
A B Match
0 x 1 True
1 y 2 False
2 z 3 True
3 r 4 False
4 x 1 True
5 z 7 False
columns = df.columns
Spróbuj tego:
df.apply(list, axis=1).apply(lambda x: True if x in list_of_lists else False)
0 True
1 False
2 True
3 False
4 True
5 False
dtype: bool
Moje podejście:
- Utwórz ramkę danych z dopasowaniami
- Połącz z oryginalnymi danymi
- Brakuje niezgodności, więc w przypadku brakujących wartości musimy wpisać False
Uważam, że to podejście można skalować w górę, nawet jeśli lista dopasowań jest duża (więc pod względem elementów apply
może być czasochłonne, ale łączenie lewostronne jest łatwe do zarządzania)
# data
data='''A|B
x|1
y|2
z|3
r|4
x|1
z|7'''
with open("a.txt", 'w') as f:
print(data, file=f)
df1 = pd.read_csv("a.txt", sep="|")
list_of_lists=[['x',1],['x',4],['z',3],['y',1]]
# First, create a data frame of matches
matches = pd.DataFrame(list_of_lists, columns=['A', 'B'])
matches['Match'] = True
# left join with the original data, non-matches will be missing, so fill with False
df1.merge(matches, on=['A', 'B'], how='left').fillna(False)
Wynik:
A B Match
0 x 1 True
1 y 2 False
2 z 3 True
3 r 4 False
4 x 1 True
5 z 7 False
Podobne pytania
Nowe pytania
python
Python to wielozadaniowy, wielozadaniowy język programowania dynamicznie typowany. Został zaprojektowany tak, aby był szybki do nauczenia się, zrozumienia i użycia oraz wymuszania czystej i jednolitej składni. Należy pamiętać, że Python 2 oficjalnie nie jest obsługiwany od 01-01-2020. Mimo to, w przypadku pytań Pythona specyficznych dla wersji, dodaj znacznik [python-2.7] lub [python-3.x]. Korzystając z wariantu Pythona (np. Jython, PyPy) lub biblioteki (np. Pandas i NumPy), należy umieścić go w tagach.