2016-03-15 1 views
2

Compte tenu de la trame de données suivantes:Pandas conditionnellement Concatenate

df = pd.DataFrame({'foo':['[a]','[b'], 
        'bar':['[a','[b]']}) 
df 
    bar foo 
0 [a] [a 
1 [b [b] 

Je veux ajouter un support de fermeture « ] » à ces cellules où les valeurs sont dépourvues. Le résultat souhaité est:

bar foo 
0 [a] [a] 
1 [b] [b] 

Cependant, je ne suis pas sûr combien de colonnes j'aurai donc je voudrais l'appliquer à l'ensemble de trame de données.

J'ai commencé avec cela, mais pas eu de chance:

df2 = df(lambda x: str(x)+"]" if (len(x)<3)) 

Merci à l'avance!

Mise à jour: Je travaille actuellement avec une table qui ressemble à ceci:

0  1  2 
0 b [r] None None 
1 c [d d [r] f[d] 
2 g [r] h [d] None 
3 m [r p [d] None 
4 b [r] n [d 
5 m [d] a [r] None 
+0

Merci pour les bonnes réponses. Je remarque que lorsque certaines cellules contiennent "None" ou sont vides, j'obtiens l'erreur suivante: IndexError: index de chaîne hors de portée. J'aurais dû montrer ce tableau dans la question initiale, mais je ne pensais pas que cela aurait de l'importance. Je l'afficherai ci-dessus. –

Répondre

2

Vous pouvez utiliser la boucle par des colonnes, car string fonction fonctionne avec Series. Utilisez indexing with str avec loc

print df 
    bar foo 
0 [a [a] 
1 [b] [b 

for cols in df.columns: 
    #print df[cols].str[-1] != ']' 
    df.loc[df[cols].str[-1] != ']', cols] = df[cols] + ']' 
print df 
    bar foo 
0 [a] [a] 
1 [b] [b] 

Ou utilisez contains avec un masque inversé par ~:

for cols in df.columns: 
    df.loc[~df[cols].str[-1].str.contains(']'), cols] = df[cols] + ']' 
print df 
    bar foo 
0 [a] [a] 
1 [b] [b]   

Merci pour commentaires de root utilisation endswith:

for cols in df.columns: 
    df.loc[~df[cols].str.endswith(']'), cols] = df[cols] + ']' 
print df 

EDIT:

S'il y a des vides strings et none valeurs:

print df 
0 [a  
1 [b] [b 
2 [a None 

for col in df.columns: 
    df.loc[~df[col].str.endswith(']').replace({np.nan: False}), col] = df[col] + ']' 
    df[col] = df[col].replace({']': ''}) 

print df 
    bar foo 
0 [a]  
1 [b] [b] 
2 [a] NaN 
+1

Je pense que l'utilisation de 'endswith' peut être plus simple que' contains'. Par exemple. '~ df [cols] .str.endswith (']')' – root

+0

Désolé, j'aurais dû mettre le commentaire ici; Et s'il y a une cellule vide? Cela semble me donner une erreur d'index: index de chaîne hors de portée. J'ai essayé ceci mais pas de dés: df2.loc [(~ df2 [cols] .str [-1] .str.endswith (']')) & (~ pd.isnull [cols]), cols] = df2 [cols ] + ']' –

+0

S'il y a 'string' vide, peut être dans la sortie' NaN'? – jezrael

1

Apprenons sur la fonction DataFrame.applymap()

df.applymap(func_reference) 

La ligne ci-dessus appellera la func_reference sur chaque cellule df. Maintenant, nous pouvons concevoir notre func_reference.

def my_filter(cell): 
    if cell[-1] == ']': 
     return cell 
    return cell + ']' 

filtered_df = df.applymap(my_filter) 

Ce n'est peut-être pas le moyen le plus efficace, mais je pense que c'est assez lisible.