如何使用pandas或numpy将一列6个整数数字分成6列,每列一个数字?
import pandas as pd
import numpy as np
df = pd.Series(range(123456,123465))
df = pd.DataFrame(df)
df.head()
Number
654321
223344
Number | x1 | x2 | x3 | x4 | x5 | x6 |
654321 | 6 | 5 | 4 | 3 | 2 | 1 |
223344 | 2 | 2 | 3 | 3 | 4 | 4 |
答案 0 :(得分:8)
这是一个简单的建议:
import pandas as pd
# MCVE dataframe:
df = pd.DataFrame([123456, 456789, 135797, 123, 123456789], columns=['number'])
def digit(x, n):
"""Return the n-th digit of integer in base 10"""
return (x // 10**n) % 10
def digitize(df, key, n):
"""Extract n less significant digits from an integer in base 10"""
for i in range(n):
df['x%d' % i] = digit(df[key], n-i-1)
# Apply function on dataframe (inplace):
digitize(df, 'number', 6)
对于试用数据框,它返回:
number x0 x1 x2 x3 x4 x5
0 123456 1 2 3 4 5 6
1 456789 4 5 6 7 8 9
2 135797 1 3 5 7 9 7
3 123 0 0 0 1 2 3
4 123456789 4 5 6 7 8 9
此方法避免了先转换为string
然后再转换为int
的需要。
它依赖于模块化整数算法,以下是操作的详细信息:
10**3 # int: 1000 (integer power)
54321 // 10**3 # int: 54 (quotient of integer division)
(54321 // 10**3) % 10 # int: 4 (remainder of integer division, modulo)
最后但并非最不重要的是,对于小于n
位或大于{的数字(注意,在后一种情况下,返回n
的低位数字),它是安全且准确的。
答案 1 :(得分:4)
假设每个数字都有6位数字,则可以在视图中找到乐趣:
u = df[['Number']].to_numpy().astype('U6').view('U1').astype(int)
df.join(pd.DataFrame(u).rename(columns=lambda c: f'x{c+1}'))
Number x1 x2 x3 x4 x5 x6
0 654321 6 5 4 3 2 1
1 223344 2 2 3 3 4 4
答案 2 :(得分:4)
您可以使用public enum Angles {
case angle1
var doubleValue: Double {
switch(self) {
case .angle1: return isiPhoneX ? 0.0 : 1.0
}
}
}
np.unravel_index
感谢@ GZ0提供一些df = pd.DataFrame({'Number': [654321,223344]})
def split_digits(df):
# get data as numpy array
numbers = df['Number'].to_numpy()
# extract digits
digits = np.unravel_index(numbers, 6*(10,))
# create column headers
columns = ['Number', *(f'x{i}' for i in "123456")]
# build and return new data frame
return pd.DataFrame(np.stack([numbers, *digits], axis=1), columns=columns, index=df.index)
split_digits(df)
# Number x1 x2 x3 x4 x5 x6
# 0 654321 6 5 4 3 2 1
# 1 223344 2 2 3 3 4 4
timeit(lambda:split_digits(df),number=1000)
# 0.3550272472202778
技巧。
答案 3 :(得分:3)
还包括一个zfill
,以防万一并非所有数字都是6位数字
dat = [list(map(int, str(x).zfill(6))) for x in df.Number]
d = pd.DataFrame(dat, df.index).rename(columns=lambda x: f'x{x + 1}')
df.join(d)
Number x1 x2 x3 x4 x5 x6
0 654321 6 5 4 3 2 1
1 223344 2 2 3 3 4 4
这得到数字
dat = [list(map(int, str(x).zfill(6))) for x in df.Number]
dat
[[6, 5, 4, 3, 2, 1], [2, 2, 3, 3, 4, 4]]
这将创建一个与df
具有相同索引的新数据框。 AND 将这些列重命名为在前面有一个'x'
,并以'x1'
而不是{ {1}}
'x0'
答案 4 :(得分:3)
虽然基于字符串的解决方案更简单,并且在大多数情况下可能足够好,但是您可以使用数学方法来完成此任务,如果您拥有大量数据集,则可以显着提高速度。
import numpy as np
import pandas as pd
df = pd.DataFrame({'Number': [654321, 223344]})
num_cols = int(np.log10(df['Number'].max() - 1)) + 1
vals = (df['Number'].values[:, np.newaxis] // (10 ** np.arange(num_cols - 1, -1, -1))) % 10
df_digits = pd.DataFrame(vals, columns=[f'x{i + 1}' for i in range(num_cols)
df2 = pd.concat([df, df_digits])], axis=1)
print(df2)
# Number x1 x2 x3 x4 x5 x6
# 0 654321 6 5 4 3 2 1
# 1 223344 2 2 3 3 4 4
答案 5 :(得分:0)
假设所有数字的长度相同(具有相等的数字位数),我将使用numpy
按照以下方式进行操作:
import numpy as np
a = np.array([[654321],[223344]])
str_a = a.astype(str)
out = np.apply_along_axis(lambda x:list(x[0]),1,str_a)
print(out)
输出:
[['6' '5' '4' '3' '2' '1']
['2' '2' '3' '3' '4' '4']]
请注意,out
当前是np.array
个中的str
,如果需要,您可以将其转换为int
。
答案 6 :(得分:0)
我真的很喜欢@ user3483203的答案。我认为.str.findall
可以使用任意数量的数字:
df = pd.DataFrame({
'Number' : [65432178888, 22334474343]
})
u = df['Number'].astype(str).str.findall(r'(\w)')
df.join(pd.DataFrame(list(u)).rename(columns=lambda c: f'x{c+1}')).apply(pd.to_numeric)
Number x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11
0 65432178888 6 5 4 3 2 1 7 8 8 8 8
1 22334474343 2 2 3 3 4 4 7 4 3 4 3
答案 7 :(得分:0)
简单的方法:
>>> df
number
0 123456
1 456789
2 135797
首先将列转换为字符串
>>> df['number'] = df['number'].astype(str)
使用字符串索引创建新列
>>> df['x1'] = df['number'].str[0]
>>> df['x2'] = df['number'].str[1]
>>> df['x3'] = df['number'].str[2]
>>> df['x4'] = df['number'].str[3]
>>> df['x5'] = df['number'].str[4]
>>> df['x6'] = df['number'].str[5]
>>> df
number x1 x2 x3 x4 x5 x6
0 123456 1 2 3 4 5 6
1 456789 4 5 6 7 8 9
2 135797 1 3 5 7 9 7
>>> df.drop('number', axis=1, inplace=True)
>>> df
x1 x2 x3 x4 x5 x6
0 1 2 3 4 5 6
1 4 5 6 7 8 9
2 1 3 5 7 9 7
@另一个str.split()
的把戏
>>> df = df['number'].str.split('(\d{1})', expand=True).add_prefix('x').drop(columns=['x0', 'x2', 'x4', 'x6', 'x8', 'x10', 'x12'])
>>> df
x1 x3 x5 x7 x9 x11
0 1 2 3 4 5 6
1 4 5 6 7 8 9
2 1 3 5 7 9 7
>>> df.rename(columns={'x3':'x2', 'x5':'x3', 'x7':'x4', 'x9':'x5', 'x11':'x6'})
x1 x2 x3 x4 x5 x6
0 1 2 3 4 5 6
1 4 5 6 7 8 9
2 1 3 5 7 9 7
>>> df = df['number'].str.split(r'(\d{1})', expand=True).T.replace('', np.nan).dropna().T
>>> df
1 3 5 7 9 11
0 1 2 3 4 5 6
1 4 5 6 7 8 9
2 1 3 5 7 9 7
>>> df.rename(columns={1:'x1', 3:'x2', 5:'x3', 7:'x4', 9:'x5', 11:'x6'})
x1 x2 x3 x4 x5 x6
0 1 2 3 4 5 6
1 4 5 6 7 8 9
2 1 3 5 7 9 7