Tôi có một khung dữ liệu 20 x 4000 trong Python bằng gấu trúc. Hai trong số các cột được đặt tên Year
và quarter
. Tôi muốn tạo một biến gọi là period
tạo Year = 2000
và quarter= q2
nhập 2000q2
.
có ai giúp được không?
Tôi có một khung dữ liệu 20 x 4000 trong Python bằng gấu trúc. Hai trong số các cột được đặt tên Year
và quarter
. Tôi muốn tạo một biến gọi là period
tạo Year = 2000
và quarter= q2
nhập 2000q2
.
có ai giúp được không?
Câu trả lời:
nếu cả hai cột là chuỗi, bạn có thể nối chúng trực tiếp:
df["period"] = df["Year"] + df["quarter"]
Nếu một (hoặc cả hai) cột không được nhập chuỗi, trước tiên bạn nên chuyển đổi nó (chúng)
df["period"] = df["Year"].astype(str) + df["quarter"]
Nếu bạn cần tham gia nhiều cột chuỗi, bạn có thể sử dụng agg
:
df['period'] = df[['Year', 'quarter', ...]].agg('-'.join, axis=1)
Trong đó "-" là dấu phân cách.
sum
.
dataframe["period"] = dataframe["Year"].map(str) + dataframe["quarter"].map(str)
bản đồ chỉ là áp dụng chuyển đổi chuỗi cho tất cả các mục.
df = pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']})
df['period'] = df[['Year', 'quarter']].apply(lambda x: ''.join(x), axis=1)
Mang lại khung dữ liệu này
Year quarter period
0 2014 q1 2014q1
1 2015 q2 2015q2
Phương pháp này tổng quát hóa thành một số cột chuỗi tùy ý bằng cách thay thế df[['Year', 'quarter']]
bằng bất kỳ lát cột nào trong khung dữ liệu của bạn, vd df.iloc[:,0:2].apply(lambda x: ''.join(x), axis=1)
.
Bạn có thể kiểm tra thêm thông tin về phương thức áp dụng () tại đây
lambda x: ''.join(x)
chỉ là ''.join
, không?
lambda x: ''.join(x)
công trình không làm gì cả; nó giống như sử dụng lambda x: sum(x)
thay vì chỉ sum
.
''.join
, tức là : df['period'] = df[['Year', 'quarter']].apply(''.join, axis=1)
.
join
chỉ mất các str
trường hợp trong một lần lặp. Sử dụng một map
để chuyển đổi tất cả thành str
và sau đó sử dụng join
.
[''.join(i) for i in zip(df["Year"].map(str),df["quarter"])]
hoặc chậm hơn một chút nhưng gọn hơn:
df.Year.str.cat(df.quarter)
df['Year'].astype(str) + df['quarter']
CẬP NHẬT: Biểu đồ thời gian Pandas 0.23.4
Hãy thử nghiệm nó trên 200 nghìn hàng DF:
In [250]: df
Out[250]:
Year quarter
0 2014 q1
1 2015 q2
In [251]: df = pd.concat([df] * 10**5)
In [252]: df.shape
Out[252]: (200000, 2)
CẬP NHẬT: thời gian mới sử dụng Pandas 0.19.0
Thời gian không tối ưu hóa CPU / GPU (được sắp xếp từ nhanh nhất đến chậm nhất):
In [107]: %timeit df['Year'].astype(str) + df['quarter']
10 loops, best of 3: 131 ms per loop
In [106]: %timeit df['Year'].map(str) + df['quarter']
10 loops, best of 3: 161 ms per loop
In [108]: %timeit df.Year.str.cat(df.quarter)
10 loops, best of 3: 189 ms per loop
In [109]: %timeit df.loc[:, ['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 567 ms per loop
In [110]: %timeit df[['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 584 ms per loop
In [111]: %timeit df[['Year','quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1)
1 loop, best of 3: 24.7 s per loop
Thời gian sử dụng tối ưu hóa CPU / GPU:
In [113]: %timeit df['Year'].astype(str) + df['quarter']
10 loops, best of 3: 53.3 ms per loop
In [114]: %timeit df['Year'].map(str) + df['quarter']
10 loops, best of 3: 65.5 ms per loop
In [115]: %timeit df.Year.str.cat(df.quarter)
10 loops, best of 3: 79.9 ms per loop
In [116]: %timeit df.loc[:, ['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 230 ms per loop
In [117]: %timeit df[['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 230 ms per loop
In [118]: %timeit df[['Year','quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1)
1 loop, best of 3: 9.38 s per loop
Trả lời đóng góp của @ anton-vbr
df.T.apply(lambda x: x.str.cat(sep=''))
Phương pháp cat()
của .str
accessor hoạt động thực sự tốt cho việc này:
>>> import pandas as pd
>>> df = pd.DataFrame([["2014", "q1"],
... ["2015", "q3"]],
... columns=('Year', 'Quarter'))
>>> print(df)
Year Quarter
0 2014 q1
1 2015 q3
>>> df['Period'] = df.Year.str.cat(df.Quarter)
>>> print(df)
Year Quarter Period
0 2014 q1 2014q1
1 2015 q3 2015q3
cat()
thậm chí cho phép bạn thêm một dấu phân cách, ví dụ: giả sử bạn chỉ có số nguyên cho năm và thời gian, bạn có thể làm điều này:
>>> import pandas as pd
>>> df = pd.DataFrame([[2014, 1],
... [2015, 3]],
... columns=('Year', 'Quarter'))
>>> print(df)
Year Quarter
0 2014 1
1 2015 3
>>> df['Period'] = df.Year.astype(str).str.cat(df.Quarter.astype(str), sep='q')
>>> print(df)
Year Quarter Period
0 2014 1 2014q1
1 2015 3 2015q3
Tham gia nhiều cột chỉ là vấn đề chuyển một danh sách chuỗi hoặc khung dữ liệu chứa tất cả trừ cột đầu tiên dưới dạng tham số str.cat()
được gọi trên cột đầu tiên (Sê-ri):
>>> df = pd.DataFrame(
... [['USA', 'Nevada', 'Las Vegas'],
... ['Brazil', 'Pernambuco', 'Recife']],
... columns=['Country', 'State', 'City'],
... )
>>> df['AllTogether'] = df['Country'].str.cat(df[['State', 'City']], sep=' - ')
>>> print(df)
Country State City AllTogether
0 USA Nevada Las Vegas USA - Nevada - Las Vegas
1 Brazil Pernambuco Recife Brazil - Pernambuco - Recife
Xin lưu ý rằng nếu chuỗi dữ liệu / chuỗi gấu trúc của bạn có giá trị null, bạn cần bao gồm tham số na nump để thay thế các giá trị NaN bằng một chuỗi, nếu không, cột kết hợp sẽ mặc định là NaN.
lambda
hoặc map
; Ngoài ra, nó chỉ đọc sạch sẽ nhất.
str.cat()
. Tôi sẽ sửa đổi câu trả lời
sep
từ khóa? trong gấu trúc-0,23,4. Cảm ơn!
sep
tham số chỉ cần thiết nếu bạn có ý định để tách các bộ phận của chuỗi nối vào nhau. Nếu bạn gặp lỗi, vui lòng cho chúng tôi xem ví dụ thất bại của bạn.
Sử dụng hàm lamba lần này với string.format ().
import pandas as pd
df = pd.DataFrame({'Year': ['2014', '2015'], 'Quarter': ['q1', 'q2']})
print df
df['YearQuarter'] = df[['Year','Quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1)
print df
Quarter Year
0 q1 2014
1 q2 2015
Quarter Year YearQuarter
0 q1 2014 2014q1
1 q2 2015 2015q2
Điều này cho phép bạn làm việc với các giá trị không phải chuỗi và định dạng lại khi cần.
import pandas as pd
df = pd.DataFrame({'Year': ['2014', '2015'], 'Quarter': [1, 2]})
print df.dtypes
print df
df['YearQuarter'] = df[['Year','Quarter']].apply(lambda x : '{}q{}'.format(x[0],x[1]), axis=1)
print df
Quarter int64
Year object
dtype: object
Quarter Year
0 1 2014
1 2 2015
Quarter Year YearQuarter
0 1 2014 2014q1
1 2 2015 2015q2
Câu trả lời đơn giản cho câu hỏi của bạn.
year quarter
0 2000 q1
1 2000 q2
> df['year_quarter'] = df['year'] + '' + df['quarter']
> print(df['year_quarter'])
2000q1
2000q2
Year
không phải là một chuỗi
df['Year'].astype(str) + '' + df['quarter'].astype(str)
Mặc dù câu trả lời @silvado là tốt nếu bạn thay đổi df.map(str)
để df.astype(str)
nó sẽ nhanh hơn:
import pandas as pd
df = pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']})
In [131]: %timeit df["Year"].map(str)
10000 loops, best of 3: 132 us per loop
In [132]: %timeit df["Year"].astype(str)
10000 loops, best of 3: 82.2 us per loop
Hãy để chúng tôi giả sử dataframe
là của bạn df
với cột Year
và Quarter
.
import pandas as pd
df = pd.DataFrame({'Quarter':'q1 q2 q3 q4'.split(), 'Year':'2000'})
Giả sử chúng ta muốn xem dataframe;
df
>>> Quarter Year
0 q1 2000
1 q2 2000
2 q3 2000
3 q4 2000
Cuối cùng, nối Year
và và Quarter
như sau.
df['Period'] = df['Year'] + ' ' + df['Quarter']
Bây giờ bạn có thể print
df
xem khung dữ liệu kết quả.
df
>>> Quarter Year Period
0 q1 2000 2000 q1
1 q2 2000 2000 q2
2 q3 2000 2000 q3
3 q4 2000 2000 q4
Nếu bạn không muốn khoảng trống giữa năm và quý, chỉ cần loại bỏ nó bằng cách thực hiện;
df['Period'] = df['Year'] + df['Quarter']
df['Period'] = df['Year'].map(str) + df['Quarter'].map(str)
TypeError: Series cannot perform the operation +
khi tôi chạy df2['filename'] = df2['job_number'] + '.' + df2['task_number']
hoặc df2['filename'] = df2['job_number'].map(str) + '.' + df2['task_number'].map(str)
.
df2['filename'] = df2['job_number'].astype(str) + '.' + df2['task_number'].astype(str)
đã làm việc.
dataframe
mà tôi đã tạo ở trên, bạn sẽ thấy rằng tất cả các cột là string
s.
Đây là một triển khai mà tôi thấy rất linh hoạt:
In [1]: import pandas as pd
In [2]: df = pd.DataFrame([[0, 'the', 'quick', 'brown'],
...: [1, 'fox', 'jumps', 'over'],
...: [2, 'the', 'lazy', 'dog']],
...: columns=['c0', 'c1', 'c2', 'c3'])
In [3]: def str_join(df, sep, *cols):
...: from functools import reduce
...: return reduce(lambda x, y: x.astype(str).str.cat(y.astype(str), sep=sep),
...: [df[col] for col in cols])
...:
In [4]: df['cat'] = str_join(df, '-', 'c0', 'c1', 'c2', 'c3')
In [5]: df
Out[5]:
c0 c1 c2 c3 cat
0 0 the quick brown 0-the-quick-brown
1 1 fox jumps over 1-fox-jumps-over
2 2 the lazy dog 2-the-lazy-dog
Khi dữ liệu của bạn được chèn vào một khung dữ liệu, lệnh này sẽ giải quyết vấn đề của bạn:
df['period'] = df[['Year', 'quarter']].apply(lambda x: ' '.join(x.astype(str)), axis=1)
hiệu quả hơn là
def concat_df_str1(df):
""" run time: 1.3416s """
return pd.Series([''.join(row.astype(str)) for row in df.values], index=df.index)
và đây là một bài kiểm tra thời gian:
import numpy as np
import pandas as pd
from time import time
def concat_df_str1(df):
""" run time: 1.3416s """
return pd.Series([''.join(row.astype(str)) for row in df.values], index=df.index)
def concat_df_str2(df):
""" run time: 5.2758s """
return df.astype(str).sum(axis=1)
def concat_df_str3(df):
""" run time: 5.0076s """
df = df.astype(str)
return df[0] + df[1] + df[2] + df[3] + df[4] + \
df[5] + df[6] + df[7] + df[8] + df[9]
def concat_df_str4(df):
""" run time: 7.8624s """
return df.astype(str).apply(lambda x: ''.join(x), axis=1)
def main():
df = pd.DataFrame(np.zeros(1000000).reshape(100000, 10))
df = df.astype(int)
time1 = time()
df_en = concat_df_str4(df)
print('run time: %.4fs' % (time() - time1))
print(df_en.head(10))
if __name__ == '__main__':
main()
cuối cùng, khi sum
(concat_df_str2) được sử dụng, kết quả không chỉ đơn giản là concat, nó sẽ chuyển sang số nguyên.
df.values[:, 0:3]
hoặc df.values[:, [0,2]]
.
khái quát cho nhiều cột, tại sao không:
columns = ['whatever', 'columns', 'you', 'choose']
df['period'] = df[columns].astype(str).sum(axis=1)
Sử dụng zip
có thể nhanh hơn:
df["period"] = [''.join(i) for i in zip(df["Year"].map(str),df["quarter"])]
Biểu đồ:
import pandas as pd
import numpy as np
import timeit
import matplotlib.pyplot as plt
from collections import defaultdict
df = pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']})
myfuncs = {
"df['Year'].astype(str) + df['quarter']":
lambda: df['Year'].astype(str) + df['quarter'],
"df['Year'].map(str) + df['quarter']":
lambda: df['Year'].map(str) + df['quarter'],
"df.Year.str.cat(df.quarter)":
lambda: df.Year.str.cat(df.quarter),
"df.loc[:, ['Year','quarter']].astype(str).sum(axis=1)":
lambda: df.loc[:, ['Year','quarter']].astype(str).sum(axis=1),
"df[['Year','quarter']].astype(str).sum(axis=1)":
lambda: df[['Year','quarter']].astype(str).sum(axis=1),
"df[['Year','quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1)":
lambda: df[['Year','quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1),
"[''.join(i) for i in zip(dataframe['Year'].map(str),dataframe['quarter'])]":
lambda: [''.join(i) for i in zip(df["Year"].map(str),df["quarter"])]
}
d = defaultdict(dict)
step = 10
cont = True
while cont:
lendf = len(df); print(lendf)
for k,v in myfuncs.items():
iters = 1
t = 0
while t < 0.2:
ts = timeit.repeat(v, number=iters, repeat=3)
t = min(ts)
iters *= 10
d[k][lendf] = t/iters
if t > 2: cont = False
df = pd.concat([df]*step)
pd.DataFrame(d).plot().legend(loc='upper center', bbox_to_anchor=(0.5, -0.15))
plt.yscale('log'); plt.xscale('log'); plt.ylabel('seconds'); plt.xlabel('df rows')
plt.show()
Giải pháp đơn giản nhất:
Giải pháp chung
df['combined_col'] = df[['col1', 'col2']].astype(str).apply('-'.join, axis=1)
Câu hỏi giải pháp cụ thể
df['quarter_year'] = df[['quarter', 'year']].astype(str).apply(''.join, axis=1)
Chỉ định dấu phân cách ưa thích bên trong dấu ngoặc kép trước .join
Giải pháp này sử dụng một bước trung gian nén hai cột của DataFrame thành một cột duy nhất chứa danh sách các giá trị. Điều này không chỉ hoạt động cho các chuỗi mà còn cho tất cả các loại kiểu cột
import pandas as pd
df = pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']})
df['list']=df[['Year','quarter']].values.tolist()
df['period']=df['list'].apply(''.join)
print(df)
Kết quả:
Year quarter list period
0 2014 q1 [2014, q1] 2014q1
1 2015 q2 [2015, q2] 2015q2
Như nhiều người đã đề cập trước đây, bạn phải chuyển đổi từng cột thành chuỗi và sau đó sử dụng toán tử cộng để kết hợp hai cột chuỗi. Bạn có thể nhận được một cải tiến hiệu suất lớn bằng cách sử dụng NumPy.
%timeit df['Year'].values.astype(str) + df.quarter
71.1 ms ± 3.76 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit df['Year'].astype(str) + df['quarter']
565 ms ± 22.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
df2['filename'] = df2['job_number'].values.astype(str) + '.' + df2['task_number'].values.astype(str)
-> Đầu ra : TypeError: ufunc 'add' did not contain a loop with signature matching types dtype('<U21') dtype('<U21') dtype('<U21')
. Cả job_number và task_number đều là ints.
df['Year'].values.astype(str) + df.quarter
Tôi nghĩ cách tốt nhất để kết hợp các cột trong gấu trúc là bằng cách chuyển đổi cả hai cột thành số nguyên và sau đó thành str.
df[['Year', 'quarter']] = df[['Year', 'quarter']].astype(int).astype(str)
df['Period']= df['Year'] + 'q' + df['quarter']
Dưới đây là tóm tắt của tôi về các giải pháp trên để ghép / kết hợp hai cột với giá trị int và str thành một cột mới, sử dụng dấu phân cách giữa các giá trị của các cột. Ba giải pháp làm việc cho mục đích này.
# be cautious about the separator, some symbols may cause "SyntaxError: EOL while scanning string literal".
# e.g. ";;" as separator would raise the SyntaxError
separator = "&&"
# pd.Series.str.cat() method does not work to concatenate / combine two columns with int value and str value. This would raise "AttributeError: Can only use .cat accessor with a 'category' dtype"
df["period"] = df["Year"].map(str) + separator + df["quarter"]
df["period"] = df[['Year','quarter']].apply(lambda x : '{} && {}'.format(x[0],x[1]), axis=1)
df["period"] = df.apply(lambda x: f'{x["Year"]} && {x["quarter"]}', axis=1)
Sử dụng .combine_first
.
df['Period'] = df['Year'].combine_first(df['Quarter'])
.combine_first
sẽ dẫn đến giá trị 'Year'
được lưu trữ trong 'Period'
, hoặc, nếu nó là Null, giá trị từ 'Quarter'
. Nó sẽ không nối hai chuỗi và lưu trữ chúng vào 'Period'
.
def madd(x):
"""Performs element-wise string concatenation with multiple input arrays.
Args:
x: iterable of np.array.
Returns: np.array.
"""
for i, arr in enumerate(x):
if type(arr.item(0)) is not str:
x[i] = x[i].astype(str)
return reduce(np.core.defchararray.add, x)
Ví dụ:
data = list(zip([2000]*4, ['q1', 'q2', 'q3', 'q4']))
df = pd.DataFrame(data=data, columns=['Year', 'quarter'])
df['period'] = madd([df[col].values for col in ['Year', 'quarter']])
df
Year quarter period
0 2000 q1 2000q1
1 2000 q2 2000q2
2 2000 q3 2000q3
3 2000 q4 2000q4
dataframe["period"] = dataframe["Year"].astype(str).add(dataframe["quarter"])
hoặc nếu các giá trị giống như [2000] [4] và muốn thực hiện [2000q4]
dataframe["period"] = dataframe["Year"].astype(str).add('q').add(dataframe["quarter"]).astype(str)
thay thế .astype(str)
bằng .map(str)
các công trình quá.
add(dataframe.iloc[:, 0:10])
ví dụ?