У меня есть фрейм данных df, и я хочу добавить '/' в колонку приведения и жанров, чтобы каждая ячейка содержала 3 '/'

id  movie      cast      genres  runtime
1   Furious    a/b/c/d   a/b        23
2   Minions    a/b/c     a/b/c      55
3   Mission    a/b       a          67
4   Kingsman   a/b/c/d   a/b/c/d    23
5   Star Wars  a         a/b/c      45

Итак, что его вывод выглядит так

id  movie      cast      genres  runtime
1   Furious    a/b/c/d   a/b//      23
2   Minions    a/b/c/    a/b/c/     55
3   Mission    a/b//     a///       67
4   Kingsman   a/b/c/d   a/b/c/d    23
5   Star Wars  a///      a/b/c/     45
2
Arsh Singh 8 Июл 2019 в 16:04

6 ответов

Лучший ответ

Вот один подход, определяющий пользовательскую функцию:

def add_values(df, *cols):
    for col in cols:
        # amount of "/" to add at each row
        c = df[col].str.count('/').rsub(3)
        # translate the above to as many "/" as required
        ap = [i * '/' for i in c.tolist()]
        # Add the above to the corresponding column
        df[col] = [i + j for i,j in zip(df[col], ap)]
    return df

add_values(df, 'cast', 'genres')

   id     movie     cast   genres  runtime
0   1   Furious  a/b/c/d    a/b//       23
1   2   Minions   a/b/c/   a/b/c/       55
2   3   Mission    a/b//     a///       67
3   4  Kingsman  a/b/c/d  a/b/c/d       23
4   5  StarWars     a///   a/b/c/       45
1
yatu 8 Июл 2019 в 13:25

Вы можете разделить на /, заполнить результирующий список пустыми строками до размера 4, а затем снова объединить с /.

Использовать .apply изменить значения во всем столбце.

Попробуй это:

import pandas as pd
from io import StringIO

df = pd.read_csv(StringIO("""id  movie      cast      genres  runtime
1   Furious    a/b/c/d   a/b        23
2   Minions    a/b/c     a/b/c      55
3   Mission    a/b       a          67
4   Kingsman   a/b/c/d   a/b/c/d    23
5   Star Wars  a         a/b/c      45"""), sep=r"\s\s+")


def pad_cells(value):
    parts = value.split("/")
    parts += [""] * (4 - len(parts))
    return "/".join(parts)


df["cast"] = df["cast"].apply(pad_cells)
df["genres"] = df["genres"].apply(pad_cells)

print(df)
0
Adam.Er8 8 Июл 2019 в 13:16

Краткое решение с itertools функциями и Dataframe.applymap:

In [217]: df
Out[217]: 
   id      movie     cast   genres  runtime
0   1    Furious  a/b/c/d      a/b       23
1   2    Minions    a/b/c    a/b/c       55
2   3    Mission      a/b        a       67
3   4   Kingsman  a/b/c/d  a/b/c/d       23
4   5  Star Wars        a    a/b/c       45

In [218]: from itertools import chain, zip_longest

In [219]: def ensure_slashes(x):
     ...:     return ''.join(chain.from_iterable(zip_longest(x.split('/'), '///', fillvalue='')))
     ...: 
     ...: 

In [220]: df[['cast','genres']] = df[['cast','genres']].applymap(ensure_slashes)

In [221]: df
Out[221]: 
   id      movie     cast   genres  runtime
0   1    Furious  a/b/c/d    a/b//       23
1   2    Minions   a/b/c/   a/b/c/       55
2   3    Mission    a/b//     a///       67
3   4   Kingsman  a/b/c/d  a/b/c/d       23
4   5  Star Wars     a///   a/b/c/       45

Важнейшая функция для применения:

def ensure_slashes(x):
    return ''.join(chain.from_iterable(zip_longest(x.split('/'), '///', fillvalue='')))
0
RomanPerekhrest 8 Июл 2019 в 13:32

Ну вот:

= ^ .. ^ =

import pandas as pd
from io import StringIO

# create raw data
raw_data = StringIO("""
id movie cast genres runtime
1 Furious a/b/c/d a/b 23
2 Minions a/b/c a/b/c 55
3 Mission a/b a 67
4 Kingsman a/b/c/d a/b/c/d 23
5 Star_Wars a a/b/c 45
""")

# load data into data frame
df = pd.read_csv(raw_data, sep=' ')

# iterate over rows and add character
for index, row in df.iterrows():
    count_character_cast = row['cast'].count('/')
    if count_character_cast < 3:
        df.set_value(index, 'cast', row['cast']+'/'*(3-int(count_character_cast)))

    count_character_genres = row['genres'].count('/')
    if count_character_genres < 3:
        df.set_value(index, 'genres', row['genres'] + '/' * (3 - int(count_character_genres)))

Выход:

   id      movie     cast   genres  runtime
0   1    Furious  a/b/c/d    a/b//       23
1   2    Minions   a/b/c/   a/b/c/       55
2   3    Mission    a/b//     a///       67
3   4   Kingsman  a/b/c/d  a/b/c/d       23
4   5  Star_Wars     a///   a/b/c/       45
0
Zaraki Kenpachi 8 Июл 2019 в 13:26

Используйте эту функцию для каждого элемента в каждом столбце, чтобы обновить их.

def update_string(string):
    total_occ = 3 #total no. of occurrences of character '/' 
    for element in string: # for each element,
        if element == "/": # if there is '/', decrease 'total_occ'
            total_occ=total_occ-1;
    for i in range(total_occ): # add remaining no. of '/' at the end
        string+="/"
    return string

x = "a/b"    
print(update_string(x))

Выход:

a/b//
0
Light Yagami 8 Июл 2019 в 13:26

Итак, идея в том, чтобы создать функцию, которая выполняет необходимую работу, и применить ее к нужным столбцам:

Функция заменит текущие косые черты пустыми строками и создаст почтовый индекс строки внутри ячейки и постоянный список косых черт с ровно 3 элементами.

Результатом является объединение элементов этого zip и Hoopla, это работает :)

import pandas as pd
import re 
df = pd.DataFrame({
                    'id': [1, 2, 3, 4, 5], 
                    'movie': ['furious', 'Mininons', 'mission', 'Kingsman', 'star Wars'], 
                    'cast': ['a/b/c/d', 'a/b/c', 'a/b', 'a/b/c/d', 'a'], 
                    'genres': ['a/b', 'a/b/c', 'a', 'a/b/c/d', 'a/b/c'],
                    'runtime': [23, 55, 67, 23, 45], 
                    })

def slash_func(x):
    slash_list = ['/'] * 3
    x = re.sub('/', '', str(x))
    list_ = list(x)

    for i in range(3 - len(list_)): 
        list_.append('')
    output_list = [v[0]+v[1] for v in list(zip(list_, slash_list))]

    return ''.join(output_list) 


df['cast'] = df['cast'].apply(lambda x: slash_func(x))
df['genres'] = df['genres'].apply(lambda x: slash_func(x))

Выход:

id  movie       cast    genres  runtime
1   furious     a/b/c/  a/b//   23
2   Mininons    a/b/c/  a/b/c/  55
3   mission     a/b//   a///    67
4   Kingsman    a/b/c/  a/b/c/  23
5   star Wars   a///    a/b/c/  45

0
Kaies LAMIRI 8 Июл 2019 в 13:39