Разрезание строк переменной длины столбцов Pandas в зависимости от условий - PullRequest
0 голосов
/ 18 декабря 2018

У меня есть фрейм данных df, например,

    A           length
0   648702831   9
1    26533315   8
2         366   3
3   354701058   9
4    25708239   8
5       70554   5
6     1574512   7
7        3975   4

Теперь я хочу создать столбец на основе таких условий, как

if ['length] == 9 or ['length] == 5:
   then ['new_col'] = First 5 Characters of ['A']

else if ['length] == 8 or ['length] == 4:
   then ['new_col'] = "0" & First 4 Characters of ['A']

else if ['length] == 7 or ['length] == 3:
   then ['new_col'] = "00" & First 3 Characters of ['A']

else 
   ['new_col'] = ['A']

Для вышеуказанных условийЯ создал следующую логику для проверки: (Для файла с 10000 строк это занимает много времени)

for i in df['length']:

    if i == 9 or i == 5:
        df['new_col'] = df['A'].astype(str).str[:5]
    elif i == 8 or i == 4:
        df['new_col'] = "0" + df['A'].astype(str).str[:4]

    elif i == 7 or i == 3:
        df['new_col'] = "00" + df['A'].astype(str).str[:3]

    else:
        df['new_col'] = df['A']

Я получаю следующий вывод:

    A          length   new_col
0   648702831   9      06487
1    26533315   8      02653
2         366   3      0366
3   354701058   9      03547
4     5708239   8      05708
5       70554   5      07055
6      1574512  7      01574
7         3975  4      03975

Этоне хочу, и кажется, что он работает только для второго условия, которое добавляет «0» впереди, когда длина равна 8 или 4.

Мне нужен мой вывод, как это,

   A           length   new_col
0   648702831   9       64870
1    26533315   8       02653
2         366   3       00366
3   354701058   9       35470
4     5708239   8       05708
5       70554   5       70554
6      1574512  7       00157
7         3975  4       03975

Как я могу добиться этого, а также если есть способ, который может занять меньше времени, это было бы здорово.Любое предложение будет оценено.

Ответы [ 4 ]

0 голосов
/ 18 декабря 2018

Исправьте ваш код

df['new_col']=''
for i,j in zip(df['length'],df.index):

    df.A = df.A.astype(str)
    if i == 9 or i == 5:
        df.loc[j,'new_col'] =  df.loc[j,'A'][:5]
    elif i == 8 or i == 4:
        df.loc[j, 'new_col'] = "0" + df.loc[j,'A'][:4]

    elif i == 7 or i == 3:
        df.loc[j, 'new_col'] = "00" + df.loc[j,'A'][:3]

    else:
        df.loc[j, 'new_col']= df.loc[j,'A']


df
Out[52]: 
           A  length new_col
0  648702831       9   64870
1   26533315       8   02653
2        366       3   00366
3  354701058       9   35470
4   25708239       8   02570
5      70554       5   70554
6    1574512       7   00157
7       3975       4   03975
0 голосов
/ 18 декабря 2018

Вы можете сделать это с помощью лямбда-функции:

df = pd.DataFrame({'A':[298347,9287384, 983, 9283, 894, 1]})
df['new_col'] = df['A'].apply(lambda x: '{0:0>8}'.format(x))

         A      Col1
0   298347  00298347
1  9287384  09287384
2      983  00000983
3     9283  00009283
4      894  00000894
5        1  00000001
0 голосов
/ 18 декабря 2018

Вы можете использовать понимание списка со словарем.Это вполне приемлемо, учитывая, что методы Панд str не векторизованы.

d = {5: 5, 9: 5, 8: 4, 4: 4, 3: 3, 7: 3}

zipper = zip(df['A'].astype(str), df['length'])

df['new_col'] = [A[:d[L]].zfill(5) if L in d else A for A, L in zipper]

print(df)

           A  length new_col
0  648702831       9   64870
1   26533315       8   02653
2        366       3   00366
3  354701058       9   35470
4   25708239       8   02570
5      70554       5   70554
6    1574512       7   00157
7       3975       4   03975
8         12       2      12
0 голосов
/ 18 декабря 2018

Использовать нарезку строк с zfill.Для скорости используйте понимание списка.

m = {1: 5, 0: 4, 3: 3}
df['new_col'] = [
    x[:m.get(y % 4, 4)].zfill(5) for x, y in zip(df['A'].astype(str), df['length'])]

df
           A  length new_col
0  648702831       9   64870
1   26533315       8   02653
2        366       3   00366
3  354701058       9   35470
4   25708239       8   02570
5      70554       5   70554
6    1574512       7   00157
7       3975       4   03975

Чтобы обработать случай по умолчанию, мы можем реализовать небольшую дополнительную проверку при вызове zfill:

df = df.append({'A' : 50, 'length': 2}, ignore_index=True)

m = {1: 5, 0: 4, 3: 3}

df['new_col'] = [
    x[:m.get(y % 4, 4)].zfill(5 if y % 4 in m else 0) 
    for x, y in zip(df['A'].astype(str), df['length'])
]

df
           A  length new_col
0  648702831       9   64870
1   26533315       8   02653
2        366       3   00366
3  354701058       9   35470
4   25708239       8   02570
5      70554       5   70554
6    1574512       7   00157
7       3975       4   03975
8         50       2      50   # Default case.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...